summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Cole <david.cole@kitware.com>2008-11-26 19:38:43 (GMT)
committerDavid Cole <david.cole@kitware.com>2008-11-26 19:38:43 (GMT)
commitceaef94cccf10a02e1bcce29d3cfa6955acf4565 (patch)
treea0cbd04050fee7082c6e3e3ad38c73877fa6f806
parent003dbff85d58d6fc2668f2e1819b413a6357b2bc (diff)
downloadCMake-ceaef94cccf10a02e1bcce29d3cfa6955acf4565.zip
CMake-ceaef94cccf10a02e1bcce29d3cfa6955acf4565.tar.gz
CMake-ceaef94cccf10a02e1bcce29d3cfa6955acf4565.tar.bz2
ENH: Implement feature request from issue 7885. Allow setting environment variables on a per-test basis for ctest using set_test_properties ENVIRONMENT.
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx2
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx20
-rw-r--r--Source/CTest/cmCTestTestHandler.h1
-rw-r--r--Source/cmCTest.cxx27
-rw-r--r--Source/cmCTest.h6
-rw-r--r--Source/cmSystemTools.cxx50
-rw-r--r--Source/cmSystemTools.h11
-rw-r--r--Tests/CMakeLists.txt13
-rw-r--r--Tests/Environment/CMakeLists.txt26
-rw-r--r--Tests/Environment/main.cxx16
10 files changed, 163 insertions, 9 deletions
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index cb713a6..92d8270 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -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)
{
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 69090d6..9a747ac 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -733,11 +733,11 @@ 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();
-
+
+ clock_finish = cmSystemTools::GetTime();
+
if ( this->LogFile )
{
double ttime = clock_finish - clock_start;
@@ -2209,7 +2209,7 @@ bool cmCTestTestHandler::SetTestsProperties(
}
}
if ( key == "DEPENDS" )
- {
+ {
std::vector<std::string> lval;
cmSystemTools::ExpandListArgument(val.c_str(), lval);
std::vector<std::string>::iterator crit;
@@ -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("=");
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index b56f817..451a477 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -90,6 +90,7 @@ public:
bool WillFail;
double Timeout;
int Index;
+ std::vector<std::string> Environment;
};
struct cmCTestTestResult
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 049248e..629282b 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -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;
}
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index a337460..2a18063 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -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
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 298d779..e47ca19 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -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()
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 1ff12bf..3726c44 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -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. */
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 1035427..05dafb0 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -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}
diff --git a/Tests/Environment/CMakeLists.txt b/Tests/Environment/CMakeLists.txt
new file mode 100644
index 0000000..2b18d24
--- /dev/null
+++ b/Tests/Environment/CMakeLists.txt
@@ -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"
+)
diff --git a/Tests/Environment/main.cxx b/Tests/Environment/main.cxx
new file mode 100644
index 0000000..2e1bf4c
--- /dev/null
+++ b/Tests/Environment/main.cxx
@@ -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;
+}