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:
David Cole 2008-11-26 14:38:43 -05:00
parent 003dbff85d
commit ceaef94ccc
10 changed files with 163 additions and 9 deletions

View File

@ -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)
{ {

View File

@ -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("=");

View File

@ -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

View File

@ -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;
} }

View File

@ -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

View File

@ -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()

View File

@ -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. */

View File

@ -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}

View File

@ -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"
)

View File

@ -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;
}