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,
remainingTime);
remainingTime, 0);
if(runTestRes != cmsysProcess_State_Exited || retval != 0)
{

View File

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

View File

@ -90,6 +90,7 @@ public:
bool WillFail;
double Timeout;
int Index;
std::vector<std::string> Environment;
};
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,
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;
}

View File

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

View File

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

View File

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

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

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