ENH: Implement feature request from issue 7885. Allow setting environment variables on a per-test basis for ctest using set_test_properties ENVIRONMENT.
This commit is contained in:
parent
003dbff85d
commit
ceaef94ccc
|
@ -382,7 +382,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
|
|||
}
|
||||
|
||||
int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, 0,
|
||||
remainingTime);
|
||||
remainingTime, 0);
|
||||
|
||||
if(runTestRes != cmsysProcess_State_Exited || retval != 0)
|
||||
{
|
||||
|
|
|
@ -733,7 +733,7 @@ void cmCTestTestHandler::ProcessOneTest(cmCTestTestProperties *it,
|
|||
if ( !this->CTest->GetShowOnly() )
|
||||
{
|
||||
res = this->CTest->RunTest(arguments, &output, &retVal, this->LogFile,
|
||||
it->Timeout);
|
||||
it->Timeout, &it->Environment);
|
||||
}
|
||||
|
||||
clock_finish = cmSystemTools::GetTime();
|
||||
|
@ -2218,6 +2218,16 @@ bool cmCTestTestHandler::SetTestsProperties(
|
|||
rtit->Depends.push_back(*crit);
|
||||
}
|
||||
}
|
||||
if ( key == "ENVIRONMENT" )
|
||||
{
|
||||
std::vector<std::string> lval;
|
||||
cmSystemTools::ExpandListArgument(val.c_str(), lval);
|
||||
std::vector<std::string>::iterator crit;
|
||||
for ( crit = lval.begin(); crit != lval.end(); ++ crit )
|
||||
{
|
||||
rtit->Environment.push_back(*crit);
|
||||
}
|
||||
}
|
||||
if ( key == "MEASUREMENT" )
|
||||
{
|
||||
size_t pos = val.find_first_of("=");
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
bool WillFail;
|
||||
double Timeout;
|
||||
int Index;
|
||||
std::vector<std::string> Environment;
|
||||
};
|
||||
|
||||
struct cmCTestTestResult
|
||||
|
|
|
@ -1105,8 +1105,12 @@ int cmCTest::RunMakeCommand(const char* command, std::string* output,
|
|||
//----------------------------------------------------------------------
|
||||
int cmCTest::RunTest(std::vector<const char*> argv,
|
||||
std::string* output, int *retVal,
|
||||
std::ostream* log, double testTimeOut)
|
||||
std::ostream* log, double testTimeOut,
|
||||
std::vector<std::string>* environment)
|
||||
{
|
||||
std::vector<std::string> origEnv;
|
||||
bool modifyEnv = (environment && environment->size()>0);
|
||||
|
||||
// determine how much time we have
|
||||
double timeout = this->GetRemainingTimeAllowed() - 120;
|
||||
if (this->TimeOut && this->TimeOut < timeout)
|
||||
|
@ -1156,6 +1160,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
|
|||
}
|
||||
std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
|
||||
|
||||
if (modifyEnv)
|
||||
{
|
||||
origEnv = cmSystemTools::AppendEnv(environment);
|
||||
}
|
||||
|
||||
*retVal = inst.Run(args, output);
|
||||
if ( *log )
|
||||
{
|
||||
|
@ -1166,6 +1175,12 @@ int cmCTest::RunTest(std::vector<const char*> argv,
|
|||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
"Internal cmCTest object used to run test." << std::endl
|
||||
<< *output << std::endl);
|
||||
|
||||
if (modifyEnv)
|
||||
{
|
||||
cmSystemTools::RestoreEnv(origEnv);
|
||||
}
|
||||
|
||||
return cmsysProcess_State_Exited;
|
||||
}
|
||||
std::vector<char> tempOutput;
|
||||
|
@ -1174,6 +1189,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
|
|||
*output = "";
|
||||
}
|
||||
|
||||
if (modifyEnv)
|
||||
{
|
||||
origEnv = cmSystemTools::AppendEnv(environment);
|
||||
}
|
||||
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_SetCommand(cp, &*argv.begin());
|
||||
cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
|
||||
|
@ -1233,6 +1253,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
|
|||
}
|
||||
cmsysProcess_Delete(cp);
|
||||
|
||||
if (modifyEnv)
|
||||
{
|
||||
cmSystemTools::RestoreEnv(origEnv);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -246,9 +246,11 @@ public:
|
|||
void SetProduceXML(bool v);
|
||||
|
||||
//! Run command specialized for tests. Returns process status and retVal is
|
||||
// return value or exception.
|
||||
// return value or exception. If environment is non-null, it is used to set
|
||||
// environment variables prior to running the test. After running the test,
|
||||
// environment variables are restored to their previous values.
|
||||
int RunTest(std::vector<const char*> args, std::string* output, int *retVal,
|
||||
std::ostream* logfile, double testTimeOut);
|
||||
std::ostream* logfile, double testTimeOut, std::vector<std::string>* environment);
|
||||
|
||||
/**
|
||||
* Execute handler and return its result. If the handler fails, it returns
|
||||
|
|
|
@ -1556,6 +1556,7 @@ bool cmSystemTools::PutEnv(const char* value)
|
|||
}
|
||||
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
//----------------------------------------------------------------------
|
||||
bool cmSystemTools::UnsetEnv(const char* value)
|
||||
{
|
||||
#if !defined(HAVE_UNSETENV)
|
||||
|
@ -1568,6 +1569,7 @@ bool cmSystemTools::UnsetEnv(const char* value)
|
|||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
|
||||
{
|
||||
std::vector<std::string> env;
|
||||
|
@ -1578,6 +1580,54 @@ std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
|
|||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
std::vector<std::string> cmSystemTools::AppendEnv(
|
||||
std::vector<std::string>* env)
|
||||
{
|
||||
std::vector<std::string> origEnv = GetEnvironmentVariables();
|
||||
|
||||
if (env && env->size()>0)
|
||||
{
|
||||
std::vector<std::string>::const_iterator eit;
|
||||
|
||||
for (eit = env->begin(); eit!= env->end(); ++eit)
|
||||
{
|
||||
PutEnv(eit->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return origEnv;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void cmSystemTools::RestoreEnv(const std::vector<std::string>& env)
|
||||
{
|
||||
std::vector<std::string>::const_iterator eit;
|
||||
|
||||
// First clear everything in the current environment:
|
||||
//
|
||||
std::vector<std::string> currentEnv = GetEnvironmentVariables();
|
||||
for (eit = currentEnv.begin(); eit!= currentEnv.end(); ++eit)
|
||||
{
|
||||
std::string var(*eit);
|
||||
|
||||
int pos = var.find("=");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
var = var.substr(0, pos);
|
||||
}
|
||||
|
||||
UnsetEnv(var.c_str());
|
||||
}
|
||||
|
||||
// Then put back each entry from the original environment:
|
||||
//
|
||||
for (eit = env.begin(); eit!= env.end(); ++eit)
|
||||
{
|
||||
PutEnv(eit->c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void cmSystemTools::EnableVSConsoleOutput()
|
||||
|
|
|
@ -335,6 +335,17 @@ public:
|
|||
|
||||
/** Get the list of all environment variables */
|
||||
static std::vector<std::string> GetEnvironmentVariables();
|
||||
|
||||
/** Append multiple variables to the current environment.
|
||||
Return the original environment, as it was before the
|
||||
append. */
|
||||
static std::vector<std::string> AppendEnv(
|
||||
std::vector<std::string>* env);
|
||||
|
||||
/** Restore the full environment to "env" - use after
|
||||
AppendEnv to put the environment back to the way it
|
||||
was. */
|
||||
static void RestoreEnv(const std::vector<std::string>& env);
|
||||
#endif
|
||||
|
||||
/** Setup the environment to enable VS 8 IDE output. */
|
||||
|
|
|
@ -497,6 +497,19 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=CVS -P ${CMake_SOURCE_DIR}/Utilities/Rel
|
|||
)
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Example")
|
||||
|
||||
ADD_TEST(Environment ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/Environment"
|
||||
"${CMake_BINARY_DIR}/Tests/Environment"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-project EnvironmentProj
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
--build-exe-dir "${CMake_BINARY_DIR}/Tests/Environment"
|
||||
--force-new-ctest-process
|
||||
--test-command ${CMAKE_CTEST_COMMAND} -VV
|
||||
)
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Environment")
|
||||
|
||||
# do each of the tutorial steps
|
||||
FOREACH(STP RANGE 1 7)
|
||||
ADD_TEST(TutorialStep${STP} ${CMAKE_CTEST_COMMAND}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
project(EnvironmentProj)
|
||||
|
||||
add_executable(Environment main.cxx)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_test(Environment1 Environment)
|
||||
add_test(Environment2 Environment)
|
||||
add_test(EchoEnvironment1 ${CMAKE_COMMAND} -E environment)
|
||||
add_test(EchoEnvironment2 ${CMAKE_COMMAND} -E environment)
|
||||
|
||||
# Make sure "CMAKE_ENV.*Happy Thanksgiving" is in the output of
|
||||
# the "1" tests:
|
||||
#
|
||||
set_tests_properties(Environment1 EchoEnvironment1 PROPERTIES
|
||||
ENVIRONMENT "CMAKE_ENVIRONMENT_TEST_VAR=Happy Thanksgiving!"
|
||||
PASS_REGULAR_EXPRESSION "CMAKE_ENV.*Happy Thanksgiving"
|
||||
)
|
||||
|
||||
# Make sure "CMAKE_ENV.*Happy Thanksgiving" is *NOT* in the output of
|
||||
# the "2" tests:
|
||||
#
|
||||
set_tests_properties(Environment2 EchoEnvironment2 PROPERTIES
|
||||
FAIL_REGULAR_EXPRESSION "CMAKE_ENV.*Happy Thanksgiving"
|
||||
)
|
|
@ -0,0 +1,16 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char* var = getenv("CMAKE_ENVIRONMENT_TEST_VAR");
|
||||
if (!var)
|
||||
{
|
||||
var = "(null)";
|
||||
}
|
||||
|
||||
fprintf(stdout, "Environment:\n");
|
||||
fprintf(stdout, " CMAKE_ENVIRONMENT_TEST_VAR='%s'\n", var);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue