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,
|
int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, 0,
|
||||||
remainingTime);
|
remainingTime, 0);
|
||||||
|
|
||||||
if(runTestRes != cmsysProcess_State_Exited || retval != 0)
|
if(runTestRes != cmsysProcess_State_Exited || retval != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -733,11 +733,11 @@ void cmCTestTestHandler::ProcessOneTest(cmCTestTestProperties *it,
|
||||||
if ( !this->CTest->GetShowOnly() )
|
if ( !this->CTest->GetShowOnly() )
|
||||||
{
|
{
|
||||||
res = this->CTest->RunTest(arguments, &output, &retVal, this->LogFile,
|
res = this->CTest->RunTest(arguments, &output, &retVal, this->LogFile,
|
||||||
it->Timeout);
|
it->Timeout, &it->Environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
clock_finish = cmSystemTools::GetTime();
|
clock_finish = cmSystemTools::GetTime();
|
||||||
|
|
||||||
if ( this->LogFile )
|
if ( this->LogFile )
|
||||||
{
|
{
|
||||||
double ttime = clock_finish - clock_start;
|
double ttime = clock_finish - clock_start;
|
||||||
|
@ -2209,7 +2209,7 @@ bool cmCTestTestHandler::SetTestsProperties(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( key == "DEPENDS" )
|
if ( key == "DEPENDS" )
|
||||||
{
|
{
|
||||||
std::vector<std::string> lval;
|
std::vector<std::string> lval;
|
||||||
cmSystemTools::ExpandListArgument(val.c_str(), lval);
|
cmSystemTools::ExpandListArgument(val.c_str(), lval);
|
||||||
std::vector<std::string>::iterator crit;
|
std::vector<std::string>::iterator crit;
|
||||||
|
@ -2218,6 +2218,16 @@ bool cmCTestTestHandler::SetTestsProperties(
|
||||||
rtit->Depends.push_back(*crit);
|
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" )
|
if ( key == "MEASUREMENT" )
|
||||||
{
|
{
|
||||||
size_t pos = val.find_first_of("=");
|
size_t pos = val.find_first_of("=");
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
bool WillFail;
|
bool WillFail;
|
||||||
double Timeout;
|
double Timeout;
|
||||||
int Index;
|
int Index;
|
||||||
|
std::vector<std::string> Environment;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmCTestTestResult
|
struct cmCTestTestResult
|
||||||
|
|
|
@ -1105,8 +1105,12 @@ int cmCTest::RunMakeCommand(const char* command, std::string* output,
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
int cmCTest::RunTest(std::vector<const char*> argv,
|
int cmCTest::RunTest(std::vector<const char*> argv,
|
||||||
std::string* output, int *retVal,
|
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
|
// determine how much time we have
|
||||||
double timeout = this->GetRemainingTimeAllowed() - 120;
|
double timeout = this->GetRemainingTimeAllowed() - 120;
|
||||||
if (this->TimeOut && this->TimeOut < timeout)
|
if (this->TimeOut && this->TimeOut < timeout)
|
||||||
|
@ -1156,6 +1160,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
|
||||||
}
|
}
|
||||||
std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
|
std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
|
||||||
|
|
||||||
|
if (modifyEnv)
|
||||||
|
{
|
||||||
|
origEnv = cmSystemTools::AppendEnv(environment);
|
||||||
|
}
|
||||||
|
|
||||||
*retVal = inst.Run(args, output);
|
*retVal = inst.Run(args, output);
|
||||||
if ( *log )
|
if ( *log )
|
||||||
{
|
{
|
||||||
|
@ -1166,6 +1175,12 @@ int cmCTest::RunTest(std::vector<const char*> argv,
|
||||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||||
"Internal cmCTest object used to run test." << std::endl
|
"Internal cmCTest object used to run test." << std::endl
|
||||||
<< *output << std::endl);
|
<< *output << std::endl);
|
||||||
|
|
||||||
|
if (modifyEnv)
|
||||||
|
{
|
||||||
|
cmSystemTools::RestoreEnv(origEnv);
|
||||||
|
}
|
||||||
|
|
||||||
return cmsysProcess_State_Exited;
|
return cmsysProcess_State_Exited;
|
||||||
}
|
}
|
||||||
std::vector<char> tempOutput;
|
std::vector<char> tempOutput;
|
||||||
|
@ -1174,6 +1189,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
|
||||||
*output = "";
|
*output = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (modifyEnv)
|
||||||
|
{
|
||||||
|
origEnv = cmSystemTools::AppendEnv(environment);
|
||||||
|
}
|
||||||
|
|
||||||
cmsysProcess* cp = cmsysProcess_New();
|
cmsysProcess* cp = cmsysProcess_New();
|
||||||
cmsysProcess_SetCommand(cp, &*argv.begin());
|
cmsysProcess_SetCommand(cp, &*argv.begin());
|
||||||
cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
|
cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
|
||||||
|
@ -1233,6 +1253,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
|
||||||
}
|
}
|
||||||
cmsysProcess_Delete(cp);
|
cmsysProcess_Delete(cp);
|
||||||
|
|
||||||
|
if (modifyEnv)
|
||||||
|
{
|
||||||
|
cmSystemTools::RestoreEnv(origEnv);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -246,9 +246,11 @@ public:
|
||||||
void SetProduceXML(bool v);
|
void SetProduceXML(bool v);
|
||||||
|
|
||||||
//! Run command specialized for tests. Returns process status and retVal is
|
//! 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,
|
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
|
* 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
|
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||||
|
//----------------------------------------------------------------------
|
||||||
bool cmSystemTools::UnsetEnv(const char* value)
|
bool cmSystemTools::UnsetEnv(const char* value)
|
||||||
{
|
{
|
||||||
#if !defined(HAVE_UNSETENV)
|
#if !defined(HAVE_UNSETENV)
|
||||||
|
@ -1568,6 +1569,7 @@ bool cmSystemTools::UnsetEnv(const char* value)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
|
std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
|
||||||
{
|
{
|
||||||
std::vector<std::string> env;
|
std::vector<std::string> env;
|
||||||
|
@ -1578,6 +1580,54 @@ std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
|
||||||
}
|
}
|
||||||
return env;
|
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
|
#endif
|
||||||
|
|
||||||
void cmSystemTools::EnableVSConsoleOutput()
|
void cmSystemTools::EnableVSConsoleOutput()
|
||||||
|
|
|
@ -335,6 +335,17 @@ public:
|
||||||
|
|
||||||
/** Get the list of all environment variables */
|
/** Get the list of all environment variables */
|
||||||
static std::vector<std::string> GetEnvironmentVariables();
|
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
|
#endif
|
||||||
|
|
||||||
/** Setup the environment to enable VS 8 IDE output. */
|
/** 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")
|
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
|
# do each of the tutorial steps
|
||||||
FOREACH(STP RANGE 1 7)
|
FOREACH(STP RANGE 1 7)
|
||||||
ADD_TEST(TutorialStep${STP} ${CMAKE_CTEST_COMMAND}
|
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