diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index f6379f528..43b8b524f 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -243,6 +243,8 @@ set(srcs core/src/ecflow/core/DurationTimer.hpp core/src/ecflow/core/Ecf.hpp core/src/ecflow/core/EcfPortLock.hpp + core/src/ecflow/core/Enumerate.hpp + core/src/ecflow/core/Environment.hpp core/src/ecflow/core/Extract.hpp core/src/ecflow/core/File.hpp core/src/ecflow/core/File_r.hpp diff --git a/libs/base/src/ecflow/base/Openssl.cpp b/libs/base/src/ecflow/base/Openssl.cpp index b6c6e32b7..97bd009be 100644 --- a/libs/base/src/ecflow/base/Openssl.cpp +++ b/libs/base/src/ecflow/base/Openssl.cpp @@ -11,9 +11,9 @@ #include "ecflow/base/Openssl.hpp" #include -#include // getenv #include +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Host.hpp" #include "ecflow/core/Str.hpp" @@ -80,8 +80,7 @@ void Openssl::enable(std::string host, const std::string& port) { } void Openssl::enable_if_defined(std::string host, const std::string& port) { - char* ecf_ssl = getenv("ECF_SSL"); - if (ecf_ssl) { + if (auto ecf_ssl = getenv(ecf::environment::ECF_SSL); ecf_ssl) { std::string ecf_ssl_env = ecf_ssl; if (host == Str::LOCALHOST()) @@ -161,7 +160,8 @@ std::string Openssl::get_password() const { } std::string Openssl::certificates_dir() const { - std::string home_path = getenv("HOME"); + std::string home_path; + ecf::environment::get_environment_variable("HOME", home_path); home_path += "/.ecflowrc/ssl/"; return home_path; } diff --git a/libs/base/src/ecflow/base/cts/task/CtsWaitCmd.cpp b/libs/base/src/ecflow/base/cts/task/CtsWaitCmd.cpp index 011e65a27..49c847b54 100644 --- a/libs/base/src/ecflow/base/cts/task/CtsWaitCmd.cpp +++ b/libs/base/src/ecflow/base/cts/task/CtsWaitCmd.cpp @@ -16,6 +16,7 @@ #include "ecflow/base/AbstractServer.hpp" #include "ecflow/base/cts/task/TaskApi.hpp" #include "ecflow/base/stc/PreAllocatedReply.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -128,7 +129,7 @@ bool TaskCmd::authenticate(AbstractServer* as, STC_Cmd_ptr& theReply) const { /// This can be done via AlterCmd by adding a variable on the task, ECF_PASS with value /// Submittable::FREE_JOBS_PASSWORD Note: this *does not* look for the variable up the node tree, only on the task. std::string ecf_pass_value; - if (submittable_->findVariableValue(Str::ECF_PASS(), ecf_pass_value)) { + if (submittable_->findVariableValue(ecf::environment::ECF_PASS, ecf_pass_value)) { if (ecf_pass_value == Submittable::FREE_JOBS_PASSWORD()) { submittable_->flag().clear(ecf::Flag::ZOMBIE); diff --git a/libs/base/src/ecflow/base/cts/task/TaskCmd.cpp b/libs/base/src/ecflow/base/cts/task/TaskCmd.cpp index 61c17dc44..c0a90fcee 100644 --- a/libs/base/src/ecflow/base/cts/task/TaskCmd.cpp +++ b/libs/base/src/ecflow/base/cts/task/TaskCmd.cpp @@ -12,6 +12,7 @@ #include "ecflow/base/AbstractServer.hpp" #include "ecflow/base/stc/PreAllocatedReply.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Submittable.hpp" @@ -123,7 +124,7 @@ bool TaskCmd::authenticate(AbstractServer* as, STC_Cmd_ptr& theReply) const { /// This can be done via AlterCmd by adding a variable on the task, ECF_PASS with value /// Submittable::FREE_JOBS_PASSWORD Note: this *does not* look for the variable up the node tree, only on the task. std::string ecf_pass_value; - if (submittable_->findVariableValue(Str::ECF_PASS(), ecf_pass_value)) { + if (submittable_->findVariableValue(ecf::environment::ECF_PASS, ecf_pass_value)) { if (ecf_pass_value == Submittable::FREE_JOBS_PASSWORD()) { submittable_->flag().clear(ecf::Flag::ZOMBIE); diff --git a/libs/base/src/ecflow/base/cts/user/AlterCmd.cpp b/libs/base/src/ecflow/base/cts/user/AlterCmd.cpp index 517c736cc..5e9d2f08e 100644 --- a/libs/base/src/ecflow/base/cts/user/AlterCmd.cpp +++ b/libs/base/src/ecflow/base/cts/user/AlterCmd.cpp @@ -20,6 +20,7 @@ #include "ecflow/base/cts/user/CtsApi.hpp" #include "ecflow/core/Converter.hpp" #include "ecflow/core/Enumerate.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Extract.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/Message.hpp" @@ -296,8 +297,8 @@ STC_Cmd_ptr AlterCmd::alter_server_state(AbstractServer* as) const { else if (change_attr_type_ == AlterCmd::VARIABLE || add_attr_type_ == AlterCmd::ADD_VARIABLE) { // ECFLOW-380: Some variable should be read only - if (name_ == Str::ECF_HOST() || name_ == Str::ECF_PORT() || name_ == "ECF_PID" || name_ == "ECF_VERSION" || - name_ == "ECF_LISTS") { + if (name_ == ecf::environment::ECF_HOST || name_ == ecf::environment::ECF_PORT || name_ == "ECF_PID" || + name_ == "ECF_VERSION" || name_ == "ECF_LISTS") { std::stringstream ss; ss << "AlterCmd:: Cannot add or change read only server variable " << name_; throw std::runtime_error(ss.str()); diff --git a/libs/base/src/ecflow/base/cts/user/CFileCmd.cpp b/libs/base/src/ecflow/base/cts/user/CFileCmd.cpp index 47ca30231..569af519e 100644 --- a/libs/base/src/ecflow/base/cts/user/CFileCmd.cpp +++ b/libs/base/src/ecflow/base/cts/user/CFileCmd.cpp @@ -18,6 +18,7 @@ #include "ecflow/base/cts/user/CtsApi.hpp" #include "ecflow/base/stc/PreAllocatedReply.hpp" #include "ecflow/core/Converter.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/node/EcfFile.hpp" #include "ecflow/node/Submittable.hpp" @@ -174,7 +175,7 @@ STC_Cmd_ptr CFileCmd::doHandleRequest(AbstractServer* as) const { case CFileCmd::JOB: { std::string ecf_job_file; - submittable->findParentVariableValue(Str::ECF_JOB(), ecf_job_file); + submittable->findParentVariableValue(ecf::environment::ECF_JOB, ecf_job_file); if (!File::open(ecf_job_file, fileContents)) { std::stringstream ss; ss << "CFileCmd::doHandleRequest: Failed to open the job file('" << ecf_job_file << "') for task " @@ -198,19 +199,19 @@ STC_Cmd_ptr CFileCmd::doHandleRequest(AbstractServer* as) const { // First try user variable, if defined this has priority ECFLOW-999 std::stringstream ss; std::string user_jobout; - if (submittable->findParentUserVariableValue(Str::ECF_JOBOUT(), user_jobout)) { + if (submittable->findParentUserVariableValue(ecf::environment::ECF_JOBOUT, user_jobout)) { if (File::open(user_jobout, fileContents)) break; ss << "Failed to open user specified job-out(ECF_JOBOUT='" << user_jobout << "') "; } - const Variable& ecf_jobout_gen_var = submittable->findGenVariable(Str::ECF_JOBOUT()); + const Variable& ecf_jobout_gen_var = submittable->findGenVariable(ecf::environment::ECF_JOBOUT); if (!File::open(ecf_jobout_gen_var.theValue(), fileContents)) { // If that fails as a backup, look under ECF_HOME/ECF_NAME.ECF_TRYNO, ECFLOW-177 preserve old SMS // behaviour std::string ecfhome_jobout; - submittable->findParentUserVariableValue(Str::ECF_HOME(), ecfhome_jobout); + submittable->findParentUserVariableValue(ecf::environment::ECF_HOME, ecfhome_jobout); ecfhome_jobout += submittable->absNodePath(); ecfhome_jobout += "."; ecfhome_jobout += submittable->tryNo(); @@ -239,7 +240,7 @@ STC_Cmd_ptr CFileCmd::doHandleRequest(AbstractServer* as) const { case CFileCmd::KILL: { std::string ecf_job_file; - submittable->findParentVariableValue(Str::ECF_JOB(), ecf_job_file); + submittable->findParentVariableValue(ecf::environment::ECF_JOB, ecf_job_file); std::string file = ecf_job_file + ".kill"; if (!File::open(file, fileContents)) { std::stringstream ss; @@ -252,7 +253,7 @@ STC_Cmd_ptr CFileCmd::doHandleRequest(AbstractServer* as) const { case CFileCmd::STAT: { std::string ecf_job_file; - submittable->findParentVariableValue(Str::ECF_JOB(), ecf_job_file); + submittable->findParentVariableValue(ecf::environment::ECF_JOB, ecf_job_file); std::string file = ecf_job_file + ".stat"; if (!File::open(file, fileContents)) { std::stringstream ss; @@ -275,7 +276,7 @@ STC_Cmd_ptr CFileCmd::doHandleRequest(AbstractServer* as) const { // First look for .man files in ECF_FILES and then ECF_HOME std::string ecf_files; - node->findParentUserVariableValue(Str::ECF_FILES(), ecf_files); + node->findParentUserVariableValue(ecf::environment::ECF_FILES, ecf_files); if (!ecf_files.empty() && fs::is_directory(ecf_files)) { std::string manFile = File::backwardSearch(ecf_files, node->absNodePath(), File::MAN_EXTN()); @@ -289,7 +290,7 @@ STC_Cmd_ptr CFileCmd::doHandleRequest(AbstractServer* as) const { if (fileContents.empty()) { // Try under ECF_HOME std::string ecf_home; - node->findParentUserVariableValue(Str::ECF_HOME(), ecf_home); + node->findParentUserVariableValue(ecf::environment::ECF_HOME, ecf_home); if (!ecf_home.empty() && fs::is_directory(ecf_home)) { std::string manFile = File::backwardSearch(ecf_home, node->absNodePath(), File::MAN_EXTN()); diff --git a/libs/base/src/ecflow/base/cts/user/LogCmd.cpp b/libs/base/src/ecflow/base/cts/user/LogCmd.cpp index b5d7a4fed..1918b77f6 100644 --- a/libs/base/src/ecflow/base/cts/user/LogCmd.cpp +++ b/libs/base/src/ecflow/base/cts/user/LogCmd.cpp @@ -17,6 +17,7 @@ #include "ecflow/base/cts/user/CtsApi.hpp" #include "ecflow/base/stc/PreAllocatedReply.hpp" #include "ecflow/core/Converter.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -145,12 +146,13 @@ STC_Cmd_ptr LogCmd::doHandleRequest(AbstractServer* as) const { // This is done adding it as a *USER* variable. This overloads the server variables // It also allows us to see the change in GUI. Note: Defs/server_variables are not synced // ECFLOW-376 - as->defs()->set_server().add_or_update_user_variables(Str::ECF_LOG(), Log::instance()->path()); + as->defs()->set_server().add_or_update_user_variables(ecf::environment::ECF_LOG, + Log::instance()->path()); } else { // User could have overridden ECF_LOG variable // *FIRST* look at user variables, then look at *server* variables. - std::string log_file_name = as->defs()->server().find_variable(Str::ECF_LOG()); + std::string log_file_name = as->defs()->server().find_variable(ecf::environment::ECF_LOG); // ECFLOW-377 should remove leading/trailing spaces from path ecf::algorithm::trim(log_file_name); diff --git a/libs/base/test/TestAlterCmd.cpp b/libs/base/test/TestAlterCmd.cpp index 1fe0f7ffc..c97d72fd5 100644 --- a/libs/base/test/TestAlterCmd.cpp +++ b/libs/base/test/TestAlterCmd.cpp @@ -17,6 +17,7 @@ #include "ecflow/base/cts/user/PathsCmd.hpp" #include "ecflow/base/cts/user/RequeueNodeCmd.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Family.hpp" @@ -956,15 +957,16 @@ BOOST_AUTO_TEST_CASE(test_alter_cmd) { { // free password TestStateChanged changed(s); std::string returnedValue; - BOOST_CHECK_MESSAGE(!task->findVariableValue(Str::ECF_PASS(), returnedValue), + BOOST_CHECK_MESSAGE(!task->findVariableValue(ecf::environment::ECF_PASS, returnedValue), "Expected no variable of name ECF_PASS"); - TestHelper::invokeRequest( - &defs, - Cmd_ptr(new AlterCmd( - task->absNodePath(), AlterCmd::ADD_VARIABLE, Str::ECF_PASS(), Submittable::FREE_JOBS_PASSWORD()))); + TestHelper::invokeRequest(&defs, + Cmd_ptr(new AlterCmd(task->absNodePath(), + AlterCmd::ADD_VARIABLE, + ecf::environment::ECF_PASS, + Submittable::FREE_JOBS_PASSWORD()))); - BOOST_CHECK_MESSAGE(task->findVariableValue(Str::ECF_PASS(), returnedValue), + BOOST_CHECK_MESSAGE(task->findVariableValue(ecf::environment::ECF_PASS, returnedValue), "Expected to find variable ECF_PASS on the task"); BOOST_CHECK_MESSAGE(returnedValue == Submittable::FREE_JOBS_PASSWORD(), "Expected variable value of name " << Submittable::FREE_JOBS_PASSWORD() << " but found " diff --git a/libs/base/test/TestArchiveAndRestoreCmd.cpp b/libs/base/test/TestArchiveAndRestoreCmd.cpp index 1fd86c158..68cbdd698 100644 --- a/libs/base/test/TestArchiveAndRestoreCmd.cpp +++ b/libs/base/test/TestArchiveAndRestoreCmd.cpp @@ -15,6 +15,7 @@ #include "ecflow/base/cts/user/DeleteCmd.hpp" #include "ecflow/base/cts/user/PathsCmd.hpp" #include "ecflow/base/cts/user/RequeueNodeCmd.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Pid.hpp" #include "ecflow/core/Str.hpp" @@ -50,7 +51,7 @@ BOOST_AUTO_TEST_CASE(test_archive_and_restore_suite) { // We use Pid::unique_name, to allow multiple invocation of this test Defs theDefs; std::string ecf_home = File::test_data("libs/base/test", "libs/base"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); suite_ptr suite = theDefs.add_suite(Pid::unique_name("test_archive_and_restore_suite")); suite->add_family("f1")->add_task("t1"); // cout << theDefs << "\n"; @@ -96,7 +97,7 @@ BOOST_AUTO_TEST_CASE(test_archive_and_restore_family) { Defs theDefs; std::string ecf_home = File::test_data("libs/base/test", "libs/base"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); suite_ptr suite = theDefs.add_suite(Pid::unique_name("test_archive_and_restore_family")); family_ptr f3 = suite->add_family("f1")->add_family("f2")->add_family("f3"); f3->add_task("t1"); @@ -147,7 +148,7 @@ BOOST_AUTO_TEST_CASE(test_archive_and_restore_all) { Defs theDefs; { std::string ecf_home = File::test_data("libs/base/test", "libs/base"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); suite_ptr suite = theDefs.add_suite(Pid::unique_name("test_archive_and_restore_all")); family_ptr f1 = suite->add_family("f1"); f1->add_task("t1"); @@ -243,7 +244,7 @@ BOOST_AUTO_TEST_CASE(test_archive_and_restore_overlap) { Defs theDefs; std::string ecf_home = File::test_data("libs/base/test", "libs/base"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); suite_ptr suite = theDefs.add_suite(Pid::unique_name("test_archive_and_restore_overlap")); std::string f1_abs_node_path; { @@ -289,7 +290,7 @@ BOOST_AUTO_TEST_CASE(test_archive_and_delete_suite) { // We use Pid::unique_name, to allow multiple invocation of this test Defs theDefs; std::string ecf_home = File::test_data("libs/base/test", "libs/base"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); suite_ptr suite = theDefs.add_suite(Pid::unique_name("test_archive_and_delete_suite")); family_ptr family = suite->add_family("f1"); family->add_task("t1"); @@ -326,7 +327,7 @@ BOOST_AUTO_TEST_CASE(test_archive_and_restore_errors) { // We use Pid::unique_name, to allow multiple invocation of this test Defs theDefs; std::string ecf_home = File::test_data("libs/base/test", "libs/base"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); suite_ptr suite = theDefs.add_suite(Pid::unique_name("test_archive_and_restore_errors")); family_ptr f1 = suite->add_family("f1"); f1->add_task("t1"); diff --git a/libs/base/test/TestCmd.cpp b/libs/base/test/TestCmd.cpp index 04dac832c..e6258bf41 100644 --- a/libs/base/test/TestCmd.cpp +++ b/libs/base/test/TestCmd.cpp @@ -18,6 +18,7 @@ #include "ecflow/base/cts/user/BeginCmd.hpp" #include "ecflow/base/cts/user/CtsCmd.hpp" #include "ecflow/core/Converter.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Family.hpp" @@ -80,7 +81,7 @@ BOOST_AUTO_TEST_CASE(test_simple_cmd) { // should be re-submitted, until the task try number > ECF_TRIES { std::string varValue; - if (t1->findParentUserVariableValue(Str::ECF_TRIES(), varValue)) { + if (t1->findParentUserVariableValue(ecf::environment::ECF_TRIES, varValue)) { auto ecf_tries = ecf::convert_to(varValue); while (true) { TestHelper::invokeRequest( diff --git a/libs/base/test/TestLogCmd.cpp b/libs/base/test/TestLogCmd.cpp index 05bf03739..55e9107bf 100644 --- a/libs/base/test/TestLogCmd.cpp +++ b/libs/base/test/TestLogCmd.cpp @@ -12,6 +12,7 @@ #include "TestHelper.hpp" #include "ecflow/base/cts/user/LogCmd.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/Str.hpp" @@ -82,7 +83,7 @@ BOOST_AUTO_TEST_CASE(test_log_cmd) { << defs.server().find_variable("ECF_LOG") << "'"); // Update ECF_LOG to have a *SPACE* at the end. ECFLOW-377 - defs.set_server().add_or_update_user_variables(Str::ECF_LOG(), new_log_file); + defs.set_server().add_or_update_user_variables(ecf::environment::ECF_LOG, new_log_file); BOOST_CHECK_MESSAGE(defs.server().find_variable("ECF_LOG") == new_log_file, "expected to find ECF_LOG with value '" << new_log_file << "' but found '" << defs.server().find_variable("ECF_LOG") << "'"); diff --git a/libs/client/src/ecflow/client/ClientEnvironment.cpp b/libs/client/src/ecflow/client/ClientEnvironment.cpp index 0511895bd..6d9a0b4e0 100644 --- a/libs/client/src/ecflow/client/ClientEnvironment.cpp +++ b/libs/client/src/ecflow/client/ClientEnvironment.cpp @@ -10,13 +10,13 @@ #include "ecflow/client/ClientEnvironment.hpp" -#include // for getenv() #include #include #include #include "ecflow/core/Converter.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Host.hpp" #include "ecflow/core/PasswdFile.hpp" @@ -223,18 +223,15 @@ std::string ClientEnvironment::toString() const { } std::string ClientEnvironment::hostSpecified() { - char* the_host = getenv(Str::ECF_HOST().c_str()); - if (the_host) - return std::string(the_host); - return std::string(); + std::string specified_host; + ecf::environment::get_environment_variable(ecf::environment::ECF_HOST, specified_host); + return specified_host; } std::string ClientEnvironment::portSpecified() { - char* theEnv = getenv(Str::ECF_PORT().c_str()); - if (theEnv) { - return std::string(theEnv); - } - return Str::DEFAULT_PORT_NUMBER(); + std::string specified_port = Str::DEFAULT_PORT_NUMBER(); + ecf::environment::get_environment_variable(ecf::environment::ECF_PORT, specified_port); + return specified_port; } void ClientEnvironment::read_environment_variables() { @@ -242,47 +239,37 @@ void ClientEnvironment::read_environment_variables() { std::cout << "ClientEnvironment::read_environment_variables()\n"; #endif - if (getenv(Str::ECF_NAME().c_str())) - task_path_ = getenv(Str::ECF_NAME().c_str()); - if (getenv(Str::ECF_PASS().c_str())) - jobs_password_ = getenv(Str::ECF_PASS().c_str()); - if (getenv(Str::ECF_TRYNO().c_str())) - task_try_num_ = atoi(getenv(Str::ECF_TRYNO().c_str())); - if (getenv("ECF_HOSTFILE")) - host_file_ = getenv("ECF_HOSTFILE"); - if (getenv(Str::ECF_RID().c_str())) - remote_id_ = getenv(Str::ECF_RID().c_str()); - if (getenv("ECF_USER")) - user_name_ = getenv("ECF_USER"); - - if (getenv("ECF_TIMEOUT")) - timeout_ = atoi(getenv("ECF_TIMEOUT")); // host file timeout - if (timeout_ > MAX_TIMEOUT) - timeout_ = MAX_TIMEOUT; - if (timeout_ < MIN_TIMEOUT) - timeout_ = MIN_TIMEOUT; - - if (getenv("ECF_ZOMBIE_TIMEOUT")) - zombie_timeout_ = atoi(getenv("ECF_ZOMBIE_TIMEOUT")); // time out for zombies - if (zombie_timeout_ > MAX_TIMEOUT) - zombie_timeout_ = MAX_TIMEOUT; - if (zombie_timeout_ < MIN_TIMEOUT) - zombie_timeout_ = MIN_TIMEOUT; - - if (getenv("ECF_CONNECT_TIMEOUT")) - connect_timeout_ = atoi(getenv("ECF_CONNECT_TIMEOUT")); // for test only - - if (getenv("ECF_DENIED")) - denied_ = true; - if (getenv("NO_ECF")) - no_ecf_ = true; - if (getenv("ECF_DEBUG_CLIENT")) - debug_ = true; - - char* debug_level = getenv("ECF_DEBUG_LEVEL"); - if (debug_level) { + ecf::environment::get_environment_variable(ecf::environment::ECF_NAME, task_path_); + + ecf::environment::get_environment_variable(ecf::environment::ECF_PASS, jobs_password_); + + ecf::environment::get_environment_variable(ecf::environment::ECF_TRYNO, task_try_num_); + + ecf::environment::get_environment_variable("ECF_HOSTFILE", host_file_); + + ecf::environment::get_environment_variable(ecf::environment::ECF_RID, remote_id_); + + ecf::environment::get_environment_variable("ECF_USER", user_name_); + + ecf::environment::get_environment_variable("ECF_TIMEOUT", timeout_); + timeout_ = timeout_ > MAX_TIMEOUT ? MAX_TIMEOUT : timeout_; + timeout_ = timeout_ < MIN_TIMEOUT ? MIN_TIMEOUT : timeout_; + + ecf::environment::get_environment_variable("ECF_ZOMBIE_TIMEOUT", zombie_timeout_); + zombie_timeout_ = (zombie_timeout_ > MAX_TIMEOUT) ? MAX_TIMEOUT : zombie_timeout_; + zombie_timeout_ = (zombie_timeout_ < MIN_TIMEOUT) ? MIN_TIMEOUT : zombie_timeout_; + + ecf::environment::get_environment_variable("ECF_CONNECT_TIMEOUT", connect_timeout_); + + ecf::environment::get_environment_variable("ECF_DENIED", denied_); + + ecf::environment::get_environment_variable("NO_ECF", no_ecf_); + + ecf::environment::get_environment_variable("ECF_DEBUG_CLIENT", debug_); + + if (auto var = getenv("ECF_DEBUG_LEVEL"); var) { try { - Ecf::set_debug_level(ecf::convert_to(debug_level)); + Ecf::set_debug_level(ecf::convert_to(var)); } catch (...) { throw std::runtime_error("The environment variable ECF_DEBUG_LEVEL must be an unsigned integer."); @@ -297,8 +284,8 @@ void ClientEnvironment::read_environment_variables() { port = host_vec_[0].second; // first entry is the config port } - if (getenv(Str::ECF_PORT().c_str())) { - port = getenv(Str::ECF_PORT().c_str()); + if (auto var = getenv(ecf::environment::ECF_PORT); var) { + port = var; host_vec_.clear(); // remove config settings, net effect is overriding host_vec_.emplace_back(host, port); } @@ -394,8 +381,7 @@ const std::string& ClientEnvironment::get_password(const char* env, const std::s return passwd_; } - char* file = getenv(env); - if (file) { + if (auto file = getenv(env); file) { std::string user_passwd_file = file; // cout << " ClientEnvironment::get_password() ECF_CUSTOM_PASSWD " << user_passwd_file << "\n"; if (!user_passwd_file.empty() && fs::exists(user_passwd_file)) { diff --git a/libs/client/test/InvokeServer.hpp b/libs/client/test/InvokeServer.hpp index ba4890eb2..70440521d 100644 --- a/libs/client/test/InvokeServer.hpp +++ b/libs/client/test/InvokeServer.hpp @@ -18,6 +18,7 @@ #include "TestHelper.hpp" #include "ecflow/client/ClientInvoker.hpp" #include "ecflow/core/EcfPortLock.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Host.hpp" #include "ecflow/core/Str.hpp" @@ -37,8 +38,9 @@ class InvokeServer { if (!msg.empty()) { std::cout << msg << " port(" << port_ << ")"; #ifdef ECF_OPENSSL - if (getenv("ECF_SSL")) + if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { std::cout << " (ssl)"; + } #endif std::cout << std::endl; } diff --git a/libs/client/test/SCPort.cpp b/libs/client/test/SCPort.cpp index 1bdf5584a..668004daa 100644 --- a/libs/client/test/SCPort.cpp +++ b/libs/client/test/SCPort.cpp @@ -15,6 +15,7 @@ #include "ecflow/client/ClientEnvironment.hpp" #include "ecflow/client/ClientInvoker.hpp" #include "ecflow/core/EcfPortLock.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Str.hpp" namespace ecf { @@ -31,17 +32,18 @@ int SCPort::thePort_ = 3144; std::string SCPort::next() { bool debug = false; - if (getenv("ECF_DEBUG_TEST")) - debug = true; + ecf::environment::get_environment_variable("ECF_DEBUG_TEST", debug); - if (debug) + if (debug) { std::cout << "\nSCPort::next() : "; + } // Allow parallel tests - char* ECF_FREE_PORT = getenv("ECF_FREE_PORT"); - if (ECF_FREE_PORT) { - if (debug) + + if (auto ECF_FREE_PORT = getenv("ECF_FREE_PORT"); ECF_FREE_PORT) { + if (debug) { std::cout << " seed_port=ECF_FREE_PORT=(" << ECF_FREE_PORT << ")"; + } std::string port = ECF_FREE_PORT; try { thePort_ = ecf::convert_to(port); @@ -54,41 +56,48 @@ std::string SCPort::next() { // This is used to test remote servers(or legacy server with new client). Here ECF_HOST=localhost in the test // scripts std::string host = ClientEnvironment::hostSpecified(); - if (debug) + if (debug) { std::cout << " ECF_HOST('" << host << "')"; + } if (host == Str::LOCALHOST()) { - char* ecf_port = getenv("ECF_PORT"); - if (ecf_port) { + if (auto ecf_port = getenv(ecf::environment::ECF_PORT); ecf_port) { std::string port = ecf_port; if (!port.empty()) { - if (debug) + if (debug) { std::cout << " ECF_PORT('" << ecf_port << "')\n"; + } return port; } } - if (debug) + if (debug) { std::cout << " !!!!!! ERROR when ECF_HOST=localhost EXPECTED ECF_PORT to be set !!!!!! "; + } } - if (debug) + if (debug) { std::cout << "\n"; + } std::string the_port = next_only(debug); - if (debug) + if (debug) { std::cout << " SCPort::next() returning free port=" << the_port << "\n"; + } return the_port; } std::string SCPort::next_only(bool debug) { - if (debug) + if (debug) { std::cout << " SCPort::next_only : starting seed_port(" << thePort_ << ")\n"; + } // Use a combination of local lock file, and pinging the server - while (!EcfPortLock::is_free(thePort_, debug)) + while (!EcfPortLock::is_free(thePort_, debug)) { thePort_++; + } - if (debug) + if (debug) { std::cout << " SCPort::next_only() seed_port(" << thePort_ << ")\n"; + } return ClientInvoker::find_free_port(thePort_, debug); } diff --git a/libs/client/test/TestJobGenOnly.cpp b/libs/client/test/TestJobGenOnly.cpp index 9a094b44e..2b06b57f4 100644 --- a/libs/client/test/TestJobGenOnly.cpp +++ b/libs/client/test/TestJobGenOnly.cpp @@ -12,6 +12,7 @@ #include // IWYU pragma: keep +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -66,7 +67,7 @@ BOOST_AUTO_TEST_CASE(test_jobgenonly) { BOOST_REQUIRE_MESSAGE(theDefs.restore(defsFile, errorMsg, warningMsg), errorMsg); // Override ECF_HOME. ECF_HOME is needed to locate to the .ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); // provide definition of ECF_CLIENT. This should replace smsinit, smscomplete, smsevent,etc // with path to the ecf client diff --git a/libs/client/test/TestServer.cpp b/libs/client/test/TestServer.cpp index 0777c7dbd..d65195265 100644 --- a/libs/client/test/TestServer.cpp +++ b/libs/client/test/TestServer.cpp @@ -17,6 +17,7 @@ #include "ecflow/client/ClientEnvironment.hpp" #include "ecflow/client/ClientInvoker.hpp" #include "ecflow/core/DurationTimer.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/core/Version.hpp" @@ -240,8 +241,9 @@ BOOST_AUTO_TEST_CASE(test_server_stress_test) { ClientInvoker theClient(invokeServer.host(), invokeServer.port()); int load = 125; #ifdef ECF_OPENSSL - if (getenv("ECF_SSL")) + if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { load = 30; + } #endif { @@ -281,10 +283,9 @@ BOOST_AUTO_TEST_CASE(test_server_stress_test) { BOOST_REQUIRE_MESSAGE(theClient.defs()->suiteVec().size() >= 1, " no suite ?"); } cout << " Server handled " << load * 16 << " requests in boost_timer(" - << boost_timer.format(3, Str::cpu_timer_format()) << ")" - << " DurationTimer(" << to_simple_string(duration_timer.elapsed()) << ")" - << " Chrono_timer(" << std::chrono::duration(chrono_timer.elapsed()).count() - << " milli)" << endl; + << boost_timer.format(3, Str::cpu_timer_format()) << ")" << " DurationTimer(" + << to_simple_string(duration_timer.elapsed()) << ")" << " Chrono_timer(" + << std::chrono::duration(chrono_timer.elapsed()).count() << " milli)" << endl; } { theClient.set_auto_sync(true); @@ -317,10 +318,9 @@ BOOST_AUTO_TEST_CASE(test_server_stress_test) { BOOST_REQUIRE_MESSAGE(theClient.defs()->suiteVec().size() >= 1, " no suite ?"); } cout << " Server handled " << load * 8 << " requests in boost_timer(" - << boost_timer.format(3, Str::cpu_timer_format()) << ")" - << " DurationTimer(" << to_simple_string(duration_timer.elapsed()) << ")" - << " Chrono_timer(" << std::chrono::duration(chrono_timer.elapsed()).count() - << " milli)" + << boost_timer.format(3, Str::cpu_timer_format()) << ")" << " DurationTimer(" + << to_simple_string(duration_timer.elapsed()) << ")" << " Chrono_timer(" + << std::chrono::duration(chrono_timer.elapsed()).count() << " milli)" << " *with* AUTO SYNC" << endl; } } @@ -359,8 +359,9 @@ BOOST_AUTO_TEST_CASE(test_server_group_stress_test) { int load = 125; #ifdef ECF_OPENSSL - if (getenv("ECF_SSL")) + if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { load = 30; + } #endif for (int i = 0; i < load; i++) { @@ -410,8 +411,9 @@ BOOST_AUTO_TEST_CASE(test_server_stress_test_2) { #endif #ifdef ECF_OPENSSL - if (getenv("ECF_SSL")) + if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { load = 10; + } #endif boost::timer::cpu_timer diff --git a/libs/client/test/TestSinglePerf.cpp b/libs/client/test/TestSinglePerf.cpp index 0dcb21391..5ec3abea4 100644 --- a/libs/client/test/TestSinglePerf.cpp +++ b/libs/client/test/TestSinglePerf.cpp @@ -8,7 +8,7 @@ * nor does it submit to any jurisdiction. */ -#include // getenv +#include #include #include @@ -347,7 +347,7 @@ void time_load_and_downloads(ClientInvoker& theClient, } BOOST_AUTO_TEST_CASE(test_perf_for_large_defs) { - if (const char* ecf_ssl = getenv("ECF_SSL"); ecf_ssl) { + if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { load_threshold_ms = 8000; // 4500; begin_threshold_ms = 800; // 400; sync_full_threshold_s = 4.5; // 2.6; @@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(test_perf_for_large_defs) { client_cmds_threshold_s = 950; // 8.5; } - if (const char* ecf_test_defs_dir = getenv("ECF_TEST_DEFS_DIR"); !ecf_test_defs_dir) { + if (auto ecf_test_defs_dir = getenv("ECF_TEST_DEFS_DIR"); !ecf_test_defs_dir) { std::cout << "Ignoring test! Environment variable ECF_TEST_DEFS_DIR is not defined\n"; } else if (!fs::exists(ecf_test_defs_dir)) { diff --git a/libs/core/src/ecflow/core/EcfPortLock.hpp b/libs/core/src/ecflow/core/EcfPortLock.hpp index 6d96909e6..1aadf806d 100644 --- a/libs/core/src/ecflow/core/EcfPortLock.hpp +++ b/libs/core/src/ecflow/core/EcfPortLock.hpp @@ -22,6 +22,7 @@ #include #include "ecflow/core/Converter.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" namespace ecf { @@ -65,12 +66,8 @@ class EcfPortLock { static std::string port_file(const std::string& the_port) { // We need the *SAME* location so that different process find the same file. // When going across compiler the root_build_dir is not sufficient - char* ecf_port_lock_dir = getenv("ECF_PORT_LOCK_DIR"); - std::string path; - if (ecf_port_lock_dir) - path = ecf_port_lock_dir; - else - path = File::root_source_dir(); + std::string path = File::root_source_dir(); + ecf::environment::get_environment_variable("ECF_PORT_LOCK_DIR", path); path += "/"; path += the_port; diff --git a/libs/core/src/ecflow/core/Environment.hpp b/libs/core/src/ecflow/core/Environment.hpp new file mode 100644 index 000000000..23d5dc7c4 --- /dev/null +++ b/libs/core/src/ecflow/core/Environment.hpp @@ -0,0 +1,126 @@ +/* + * Copyright 2009- ECMWF. + * + * This software is licensed under the terms of the Apache Licence version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * In applying this licence, ECMWF does not waive the privileges and immunities + * granted to it by virtue of its status as an intergovernmental organisation + * nor does it submit to any jurisdiction. + */ + +#ifndef ecflow_core_Environment_HPP +#define ecflow_core_Environment_HPP + +namespace ecf { + +namespace environment { + +constexpr const char* ECF_PORT = "ECF_PORT"; +constexpr const char* ECF_RID = "ECF_RID"; +constexpr const char* ECF_TRYNO = "ECF_TRYNO"; +constexpr const char* ECF_TRIES = "ECF_TRIES"; +constexpr const char* ECF_NAME = "ECF_NAME"; +constexpr const char* ECF_HOST = "ECF_HOST"; +constexpr const char* ECF_HOST_PROTOCOL = "ECF_HOST_PROTOCOL"; +constexpr const char* ECF_PASS = "ECF_PASS"; +constexpr const char* ECF_JOB = "ECF_JOB"; +constexpr const char* ECF_JOBOUT = "ECF_JOBOUT"; +constexpr const char* ECF_SCRIPT = "ECF_SCRIPT"; +constexpr const char* ECF_DUMMY_TASK = "ECF_DUMMY_TASK"; +constexpr const char* ECF_NO_SCRIPT = "ECF_NO_SCRIPT"; +constexpr const char* ECF_MICRO = "ECF_MICRO"; +constexpr const char* ECF_FILES = "ECF_FILES"; +constexpr const char* ECF_FETCH = "ECF_FETCH"; +constexpr const char* ECF_KILL_CMD = "ECF_KILL_CMD"; +constexpr const char* ECF_STATUS_CMD = "ECF_STATUS_CMD"; +constexpr const char* ECF_HOME = "ECF_HOME"; +constexpr const char* ECF_INCLUDE = "ECF_INCLUDE"; +constexpr const char* ECF_JOB_CMD = "ECF_JOB_CMD"; +constexpr const char* ECF_OUT = "ECF_OUT"; +constexpr const char* ECF_EXTN = "ECF_EXTN"; +constexpr const char* ECF_LOG = "ECF_LOG"; +constexpr const char* ECF_PASSWD = "ECF_PASSWD"; +constexpr const char* ECF_CUSTOM_PASSWD = "ECF_CUSTOM_PASSWD"; + +constexpr const char* ECF_SSL = "ECF_SSL"; +constexpr const char* ECF_USER = "ECF_USER"; + +namespace /* anonymous */ { + +template +struct Environment +{ + static void get(const char* name, T& value) { + if (auto var = std::getenv(name); var) { + value = T{var}; + } + } +}; + +template <> +struct Environment +{ + static void get(const char* name, int& value) { + if (auto var = std::getenv(name); var) { + value = atoi(var); + } + } +}; + +template <> +struct Environment +{ + static void get(const char* name, unsigned int& value) { + if (auto var = std::getenv(name); var) { + value = atoi(var); + } + } +}; + +template <> +struct Environment +{ + static void get(const char* name, long& value) { + if (auto var = std::getenv(name); var) { + value = atol(var); + } + } +}; + +template <> +struct Environment +{ + static void get(const char* name, bool& value) { + if (auto var = std::getenv(name); var) { + value = true; + } + } +}; + +} // namespace + +/** + * @brief Retrieves the environment variable value and stores it in the given variable. + * If the environment variable is not set, the variable is left unchanged. + * + * In case of integral types, the environment variable is converted to the corresponding type. + * In case of bool type, if the environment variable is set, the variable is set to true. + * + * @tparam T + * @param name + * @param value + */ +template +void get_environment_variable(const char* name, T& value) { + Environment::get(name, value); +} + +inline bool has_environment_variable(const char* name) { + return std::getenv(name) != nullptr; +} + +}; // namespace environment + +} // namespace ecf + +#endif /* ecflow_core_Environment_HPP */ diff --git a/libs/core/src/ecflow/core/Host.cpp b/libs/core/src/ecflow/core/Host.cpp index f2db501bd..4f75a8491 100644 --- a/libs/core/src/ecflow/core/Host.cpp +++ b/libs/core/src/ecflow/core/Host.cpp @@ -15,6 +15,7 @@ #include // for gethostname #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Str.hpp" using namespace std; @@ -67,11 +68,11 @@ std::string Host::ecf_lists_file(const std::string& port) const { } std::string Host::ecf_passwd_file(const std::string& port) const { - return prefix_host_and_port(port, Str::ECF_PASSWD()); + return prefix_host_and_port(port, ecf::environment::ECF_PASSWD); } std::string Host::ecf_custom_passwd_file(const std::string& port) const { - return prefix_host_and_port(port, Str::ECF_CUSTOM_PASSWD()); + return prefix_host_and_port(port, ecf::environment::ECF_CUSTOM_PASSWD); } std::string Host::prefix_host_and_port(const std::string& port, const std::string& file_name) const { diff --git a/libs/core/src/ecflow/core/Str.cpp b/libs/core/src/ecflow/core/Str.cpp index 593022c41..aa1957323 100644 --- a/libs/core/src/ecflow/core/Str.cpp +++ b/libs/core/src/ecflow/core/Str.cpp @@ -79,112 +79,10 @@ const std::string& Str::LOCALHOST() { return localhost; } -const std::string& Str::ECF_PORT() { - static std::string ECF_PORT = "ECF_PORT"; - return ECF_PORT; -} -const std::string& Str::ECF_RID() { - static std::string ECF_RID = "ECF_RID"; - return ECF_RID; -} -const std::string& Str::ECF_TRYNO() { - static std::string ECF_TRYNO = "ECF_TRYNO"; - return ECF_TRYNO; -} -const std::string& Str::ECF_TRIES() { - static std::string ECF_TRIES = "ECF_TRIES"; - return ECF_TRIES; -} -const std::string& Str::ECF_NAME() { - static std::string ECF_NAME = "ECF_NAME"; - return ECF_NAME; -} -const std::string& Str::ECF_HOST() { - static std::string ECF_HOST = "ECF_HOST"; - return ECF_HOST; -} -const std::string& Str::ECF_PASS() { - static std::string ECF_PASS = "ECF_PASS"; - return ECF_PASS; -} -const std::string& Str::ECF_JOB() { - static std::string ECF_JOB = "ECF_JOB"; - return ECF_JOB; -} -const std::string& Str::ECF_JOBOUT() { - static std::string ECF_JOBOUT = "ECF_JOBOUT"; - return ECF_JOBOUT; -} -const std::string& Str::ECF_SCRIPT() { - static std::string ECF_SCRIPT = "ECF_SCRIPT"; - return ECF_SCRIPT; -} -const std::string& Str::ECF_DUMMY_TASK() { - static std::string ECF_DUMMY_TASK = "ECF_DUMMY_TASK"; - return ECF_DUMMY_TASK; -} -const std::string& Str::ECF_NO_SCRIPT() { - static std::string ECF_NO_SCRIPT = "ECF_NO_SCRIPT"; - return ECF_NO_SCRIPT; -} -const std::string& Str::ECF_MICRO() { - static std::string ECF_MICRO = "ECF_MICRO"; - return ECF_MICRO; -} -const std::string& Str::ECF_FILES() { - static std::string ECF_FILES = "ECF_FILES"; - return ECF_FILES; -} -const std::string& Str::ECF_FETCH() { - static std::string ECF_FETCH = "ECF_FETCH"; - return ECF_FETCH; -} -const std::string& Str::ECF_KILL_CMD() { - static std::string ECF_KILL_CMD = "ECF_KILL_CMD"; - return ECF_KILL_CMD; -} -const std::string& Str::ECF_STATUS_CMD() { - static std::string ECF_STATUS_CMD = "ECF_STATUS_CMD"; - return ECF_STATUS_CMD; -} - -const std::string& Str::ECF_HOME() { - static std::string ECF_HOME = "ECF_HOME"; - return ECF_HOME; -} -const std::string& Str::ECF_INCLUDE() { - static std::string ECF_INCLUDE = "ECF_INCLUDE"; - return ECF_INCLUDE; -} -const std::string& Str::ECF_JOB_CMD() { - static std::string ECF_JOB_CMD = "ECF_JOB_CMD"; - return ECF_JOB_CMD; -} -const std::string& Str::ECF_OUT() { - static std::string ECF_OUT = "ECF_OUT"; - return ECF_OUT; -} -const std::string& Str::ECF_EXTN() { - static std::string ECF_EXTN = "ECF_EXTN"; - return ECF_EXTN; -} -const std::string& Str::ECF_LOG() { - static std::string ECF_LOG = "ECF_LOG"; - return ECF_LOG; -} - const std::string& Str::WHITE_LIST_FILE() { static std::string WHITE_LIST_FILE = "ecf.lists"; return WHITE_LIST_FILE; } -const std::string& Str::ECF_PASSWD() { - static std::string ECF_PASSWD = "ecf.passwd"; - return ECF_PASSWD; -} -const std::string& Str::ECF_CUSTOM_PASSWD() { - static std::string ECF_CUSTOM_PASSWD = "ecf.custom_passwd"; - return ECF_CUSTOM_PASSWD; -} const std::string& Str::ALPHANUMERIC_UNDERSCORE() { static string ALPHANUMERIC_UNDERSCORE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; diff --git a/libs/core/src/ecflow/core/Str.hpp b/libs/core/src/ecflow/core/Str.hpp index 2de926364..cb478c863 100644 --- a/libs/core/src/ecflow/core/Str.hpp +++ b/libs/core/src/ecflow/core/Str.hpp @@ -206,34 +206,7 @@ class Str { static const std::string& DEFAULT_PORT_NUMBER(); // "3141" static const std::string& LOCALHOST(); - static const std::string& ECF_PORT(); - static const std::string& ECF_RID(); - static const std::string& ECF_TRYNO(); - static const std::string& ECF_TRIES(); - static const std::string& ECF_NAME(); - static const std::string& ECF_HOST(); - static const std::string& ECF_PASS(); - static const std::string& ECF_JOB(); - static const std::string& ECF_JOBOUT(); - static const std::string& ECF_SCRIPT(); - static const std::string& ECF_DUMMY_TASK(); - static const std::string& ECF_NO_SCRIPT(); - static const std::string& ECF_MICRO(); - static const std::string& ECF_FILES(); - static const std::string& ECF_FETCH(); - static const std::string& ECF_KILL_CMD(); - static const std::string& ECF_STATUS_CMD(); - - static const std::string& ECF_HOME(); - static const std::string& ECF_INCLUDE(); - static const std::string& ECF_JOB_CMD(); - static const std::string& ECF_OUT(); - static const std::string& ECF_EXTN(); - static const std::string& ECF_LOG(); - static const std::string& WHITE_LIST_FILE(); - static const std::string& ECF_PASSWD(); - static const std::string& ECF_CUSTOM_PASSWD(); static const char* cpu_timer_format() { return "%ws wall, (%us user + %ss system = %ts) CPU (%p%)"; } }; diff --git a/libs/core/test/TestFile.cpp b/libs/core/test/TestFile.cpp index 9c47c8d4e..13418614d 100644 --- a/libs/core/test/TestFile.cpp +++ b/libs/core/test/TestFile.cpp @@ -8,7 +8,6 @@ * nor does it submit to any jurisdiction. */ -#include // for getenv() #include // for std::ofstream #include #include @@ -16,6 +15,7 @@ #include #include "ecflow/core/Converter.hpp" +#include "ecflow/core/Environment.hpp" // #define FILE_PERF_CHECK_IMPLEMENTATIONS 1; #ifdef FILE_PERF_CHECK_IMPLEMENTATIONS @@ -329,7 +329,7 @@ BOOST_AUTO_TEST_CASE(test_create_missing_directories) { cout << "ACore:: ...test_create_missing_directories"; // This test FAIL's randomly on the cray in BATCH mode, but passes in interactive mode. - if (getenv("ECFLOW_CRAY_BATCH")) { + if (ecf::environment::has_environment_variable("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } diff --git a/libs/core/test/TestSanitizerAS.cpp b/libs/core/test/TestSanitizerAS.cpp index 217e27b6d..0de7b333c 100644 --- a/libs/core/test/TestSanitizerAS.cpp +++ b/libs/core/test/TestSanitizerAS.cpp @@ -12,6 +12,8 @@ #include +#include "ecflow/core/Environment.hpp" + using namespace boost; using namespace std; @@ -31,22 +33,24 @@ int integer_returning_function() { #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif +boost::test_tools::assertion_result is_testing_address_sanitizer([[maybe_unused]] boost::unit_test::test_unit_id id) { + return ecf::environment::has_environment_variable("ECF_TEST_SANITIZER_AS"); +} + // *** This test does not seem work with address sanitiser **** -BOOST_AUTO_TEST_CASE(test_sanitizer_use_of_out_of_scope_stack_memory) { - char* test_me = getenv("ECF_TEST_SANITIZER_AS"); - if (test_me) { - cout << "ACore:: ...test_sanitizer_use_of_out_of_scope_stack_memory\n"; - - int* pointer = NULL; - if (bool_returning_function()) { - int value = integer_returning_function(); - pointer = &value; - } - cout << "dodgy pointer:" << *pointer << "\n"; // Error: invalid access of stack memory out of declaration scope - *pointer = 42; - cout << "dodgy pointer:" << *pointer << "\n"; - BOOST_CHECK_MESSAGE(true, "stop boost test from complaining"); +BOOST_AUTO_TEST_CASE(test_sanitizer_use_of_out_of_scope_stack_memory, + *boost::unit_test::precondition(is_testing_address_sanitizer)) { + cout << "ACore:: ...test_sanitizer_use_of_out_of_scope_stack_memory\n"; + + int* pointer = NULL; + if (bool_returning_function()) { + int value = integer_returning_function(); + pointer = &value; } + cout << "dodgy pointer:" << *pointer << "\n"; // Error: invalid access of stack memory out of declaration scope + *pointer = 42; + cout << "dodgy pointer:" << *pointer << "\n"; + BOOST_CHECK_MESSAGE(true, "stop boost test from complaining"); } #if defined(__GNUC__) and !defined(__clang__) @@ -58,20 +62,17 @@ BOOST_AUTO_TEST_CASE(test_sanitizer_use_of_out_of_scope_stack_memory) { #pragma GCC diagnostic ignored "-Warray-bounds" #endif -BOOST_AUTO_TEST_CASE(test_sanitizer_vector_overflow) { - char* test_me = getenv("ECF_TEST_SANITIZER_AS"); - if (test_me) { - cout << "ACore:: ...test_sanitizer_vector_overflow\n"; - // This check detects when a libc++ container is accessed beyond the region [container.begin(), container.end()) - // — even when the accessed memory is in a heap-allocated buffer used internally by a container. - - // the following example, the vector variable has valid indexes in the range [0, 2], but is accessed at index 3, - // causing an overflow. - std::vector vector{0, 1, 2}; - auto* pointer = &vector[0]; - cout << pointer[3]; // Error: out of bounds access for vector - BOOST_CHECK_MESSAGE(true, "stop boost test from complaining"); - } +BOOST_AUTO_TEST_CASE(test_sanitizer_vector_overflow, *boost::unit_test::precondition(is_testing_address_sanitizer)) { + cout << "ACore:: ...test_sanitizer_vector_overflow\n"; + // This check detects when a libc++ container is accessed beyond the region [container.begin(), container.end()) + // — even when the accessed memory is in a heap-allocated buffer used internally by a container. + + // the following example, the vector variable has valid indexes in the range [0, 2], but is accessed at index 3, + // causing an overflow. + std::vector vector{0, 1, 2}; + auto* pointer = &vector[0]; + cout << pointer[3]; // Error: out of bounds access for vector + BOOST_CHECK_MESSAGE(true, "stop boost test from complaining"); } #if defined(__GNUC__) and !defined(__clang__) diff --git a/libs/core/test/TestSanitizerUB.cpp b/libs/core/test/TestSanitizerUB.cpp index cbd20c4e9..9a8f7ae1b 100644 --- a/libs/core/test/TestSanitizerUB.cpp +++ b/libs/core/test/TestSanitizerUB.cpp @@ -12,6 +12,8 @@ #include +#include "ecflow/core/Environment.hpp" + using namespace boost; using namespace std; @@ -36,60 +38,59 @@ Derived* getDerived() { #pragma GCC diagnostic ignored "-Warray-bounds" #endif -BOOST_AUTO_TEST_CASE(test_sanitizer_invalid_object_size) { - char* test_me = getenv("ECF_TEST_SANITIZER_UB"); - if (test_me) { - cout << "ACore:: ...test_sanitizer_invalid_object_size\n"; +boost::test_tools::assertion_result +is_testing_undefined_behaviour_sanitizer([[maybe_unused]] boost::unit_test::test_unit_id id) { + return ecf::environment::has_environment_variable("ECF_TEST_SANITIZER_UB"); +} + +BOOST_AUTO_TEST_CASE(test_sanitizer_invalid_object_size, + *boost::unit_test::precondition(is_testing_undefined_behaviour_sanitizer)) { + cout << "ACore:: ...test_sanitizer_invalid_object_size\n"; - // This check detects pointer casts in which the size of the source type is less than the size of the - // destination type. Using the result of such a cast to access out-of-bounds data has undefined behaviour - cout << getDerived()->pad2 << "\n"; - BOOST_CHECK_MESSAGE(true, "stop boost test from complaining"); - } + // This check detects pointer casts in which the size of the source type is less than the size of the + // destination type. Using the result of such a cast to access out-of-bounds data has undefined behaviour + cout << getDerived()->pad2 << "\n"; + BOOST_CHECK_MESSAGE(true, "stop boost test from complaining"); } #if defined(__GNUC__) and !defined(__clang__) #pragma GCC diagnostic pop #endif -BOOST_AUTO_TEST_CASE(test_sanitizer_misaligned_structure_pointer_assignment) { - char* test_me = getenv("ECF_TEST_SANITIZER_UB"); - if (test_me) { - cout << "ACore:: ...test_sanitizer_misaligned_structure_pointer_assignment\n"; - // In the following example, the pointer variable is required to have 8-byte alignment, but is only 1-byte - // aligned. - - struct A - { - int32_t i32; - int64_t i64; - }; - int8_t* buffer = (int8_t*)malloc(32); - struct A* pointer = (struct A*)(buffer + 1); - pointer->i32 = 7; // Error: pointer is misaligned - - BOOST_CHECK_MESSAGE(pointer->i32 == 7, "expected error"); - - // solution - // One solution is to mark the struct as packed. In the following example, the A structure is packed, - // preventing the compiler from adding padding between members. - // struct A { ... } __attribute__((packed)); - BOOST_CHECK_MESSAGE(true, "stop boost test from complaining"); - } +BOOST_AUTO_TEST_CASE(test_sanitizer_misaligned_structure_pointer_assignment, + *boost::unit_test::precondition(is_testing_undefined_behaviour_sanitizer)) { + cout << "ACore:: ...test_sanitizer_misaligned_structure_pointer_assignment\n"; + // In the following example, the pointer variable is required to have 8-byte alignment, but is only 1-byte + // aligned. + + struct A + { + int32_t i32; + int64_t i64; + }; + int8_t* buffer = (int8_t*)malloc(32); + struct A* pointer = (struct A*)(buffer + 1); + pointer->i32 = 7; // Error: pointer is misaligned + + BOOST_CHECK_MESSAGE(pointer->i32 == 7, "expected error"); + + // solution + // One solution is to mark the struct as packed. In the following example, the A structure is packed, + // preventing the compiler from adding padding between members. + // struct A { ... } __attribute__((packed)); + BOOST_CHECK_MESSAGE(true, "stop boost test from complaining"); } -BOOST_AUTO_TEST_CASE(test_sanitizer_out_of_bounds_array_access) { - char* test_me = getenv("ECF_TEST_SANITIZER_UB"); - if (test_me) { - cout << "ACore:: ...test_sanitizer_out_of_bounds_array_access\n"; - - // This check detects out-of-bounds access of arrays with fixed or variable-length sizes. - // Out-of-bounds array accesses have undefined behaviour, and can result in crashes or incorrect program output. - int array[5] = {0, 0, 0, 0, 0}; - for (int i = 0; i <= 5; ++i) { - array[i] += 1; // Error: out-of-bounds access on the last iteration - BOOST_REQUIRE_NO_THROW(array[i] += 1); - } +BOOST_AUTO_TEST_CASE(test_sanitizer_out_of_bounds_array_access, + *boost::unit_test::precondition(is_testing_undefined_behaviour_sanitizer)) { + cout << "ACore:: ...test_sanitizer_out_of_bounds_array_access\n"; + + // This check detects out-of-bounds access of arrays with fixed or variable-length sizes. + // Out-of-bounds array accesses have undefined behaviour, and can result in crashes or incorrect program output. + int array[5] = {0, 0, 0, 0, 0}; + for (int i = 0; i <= 5; ++i) { + array[i] += 1; // Error: out-of-bounds access on the last iteration + BOOST_REQUIRE_NO_THROW(array[i] += 1); } } @@ -104,15 +105,13 @@ struct A } }; -BOOST_AUTO_TEST_CASE(test_sanitizer_member_access_through_null_pointer) { - char* test_me = getenv("ECF_TEST_SANITIZER_UB"); - if (test_me) { - cout << "ACore:: ...test_sanitizer_member_access_through_null_pointer \n"; +BOOST_AUTO_TEST_CASE(test_sanitizer_member_access_through_null_pointer, + *boost::unit_test::precondition(is_testing_undefined_behaviour_sanitizer)) { + cout << "ACore:: ...test_sanitizer_member_access_through_null_pointer \n"; - A* a = nullptr; - int x = a->getX(); // Error: member access through null pointer - BOOST_CHECK_MESSAGE(x, "stop boost test from complaining"); - } + A* a = nullptr; + int x = a->getX(); // Error: member access through null pointer + BOOST_CHECK_MESSAGE(x, "stop boost test from complaining"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/libs/node/src/ecflow/node/EcfFile.cpp b/libs/node/src/ecflow/node/EcfFile.cpp index f3e20521c..953205289 100644 --- a/libs/node/src/ecflow/node/EcfFile.cpp +++ b/libs/node/src/ecflow/node/EcfFile.cpp @@ -20,6 +20,7 @@ #include "ecflow/core/Converter.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/Str.hpp" @@ -99,7 +100,7 @@ EcfFile::EcfFile(Node* t, script_path_or_cmd_(pathToEcfFileOrCommand), script_origin_(script_origin), ecf_file_search_algorithm_(search_algo) { - node_->findParentUserVariableValue(Str::ECF_MICRO(), ecfMicroCache_); + node_->findParentUserVariableValue(ecf::environment::ECF_MICRO, ecfMicroCache_); if (ecfMicroCache_.empty() || ecfMicroCache_.size() != 1) { std::stringstream ss; ss << "EcfFile::EcfFile: Node " << t->absNodePath() << " is referencing a invalid ECF_MICRO variable(' " @@ -454,7 +455,7 @@ std::vector EcfFile::get_ecf_include_paths(const EcfFile& ecf) { const Node& node = *ecf.node_; std::string ecf_include; - node.findParentUserVariableValue(Str::ECF_INCLUDE(), ecf_include); + node.findParentUserVariableValue(ecf::environment::ECF_INCLUDE, ecf_include); std::vector paths; if (!ecf_include.empty()) { @@ -902,19 +903,19 @@ void EcfFile::get_used_variables(std::string& used_variables) const { // to modify. Hence, we have also excluded generated variables SUITE, FAMILY, TASK // **************************************************************************************** for (std::pair item : used_variables_map) { - if (item.first.find(Str::ECF_TRYNO()) != std::string::npos) + if (item.first.find(ecf::environment::ECF_TRYNO) != std::string::npos) continue; - if (item.first.find(Str::ECF_JOB()) != std::string::npos) + if (item.first.find(ecf::environment::ECF_JOB) != std::string::npos) continue; - if (item.first.find(Str::ECF_JOBOUT()) != std::string::npos) + if (item.first.find(ecf::environment::ECF_JOBOUT) != std::string::npos) continue; - if (item.first.find(Str::ECF_PASS()) != std::string::npos) + if (item.first.find(ecf::environment::ECF_PASS) != std::string::npos) continue; - if (item.first.find(Str::ECF_PORT()) != std::string::npos) + if (item.first.find(ecf::environment::ECF_PORT) != std::string::npos) continue; - if (item.first.find(Str::ECF_HOST()) != std::string::npos) + if (item.first.find(ecf::environment::ECF_HOST) != std::string::npos) continue; - if (item.first.find(Str::ECF_NAME()) != std::string::npos) + if (item.first.find(ecf::environment::ECF_NAME) != std::string::npos) continue; // We must use exact match, to avoid user variables like ESUITE,EFAMILY,ETASK @@ -1044,7 +1045,7 @@ const std::string& EcfFile::doCreateJobFile(JobsParam& jobsParam) const { // b/ The value of the user variable has a valid directory paths and job file name // c/ The user will lose the try number. std::string ecf_job; - if (!node_->findParentVariableValue(Str::ECF_JOB(), ecf_job)) { + if (!node_->findParentVariableValue(ecf::environment::ECF_JOB, ecf_job)) { LOG_ASSERT(!ecf_job.empty(), "EcfFile::doCreateJobFile: ECF_JOB should have been generated, program error"); } @@ -1123,7 +1124,7 @@ std::string EcfFile::script_or_job_path() const { // ECF_FETCH or ECF_SCRIPT_CMD std::string ecf_job; - (void)node_->findParentVariableValue(Str::ECF_JOB(), ecf_job); + (void)node_->findParentVariableValue(ecf::environment::ECF_JOB, ecf_job); return ecf_job; } @@ -1739,7 +1740,7 @@ std::string PreProcessor::getIncludedFilePath(const std::string& includedFile1, // WE get HERE *if* ECF_INCLUDE not specified, or if specified but file *not found* std::string ecf_include; - node->findParentVariableValue(Str::ECF_HOME(), ecf_include); + node->findParentVariableValue(ecf::environment::ECF_HOME, ecf_include); if (ecf_include.empty()) { std::stringstream ss; ss << "ECF_INCLUDE/ECF_HOME not specified, at : " << line; @@ -1778,7 +1779,7 @@ std::string PreProcessor::getIncludedFilePath(const std::string& includedFile1, } // include contents of %ECF_HOME%/%SUITE%/%FAMILY%/filename - node->findParentUserVariableValue(Str::ECF_HOME(), path); + node->findParentUserVariableValue(ecf::environment::ECF_HOME, path); if (path.empty()) { std::stringstream ss; ss << "ECF_HOME not specified, at : " << line; @@ -1867,7 +1868,7 @@ bool IncludeFileCache::lines(std::vector& lns) { string line; while (std::getline(fp_, line)) { lns.push_back(line); - } // c++11 + } // c++11 fp_.clear(); // eol fp_ will be in bad state reset. So we can re-use no_of_lines_ = lns.size(); // cache for next time diff --git a/libs/node/src/ecflow/node/Node.cpp b/libs/node/src/ecflow/node/Node.cpp index 712866388..7ccd0c14f 100644 --- a/libs/node/src/ecflow/node/Node.cpp +++ b/libs/node/src/ecflow/node/Node.cpp @@ -15,6 +15,7 @@ #include "ecflow/attribute/AutoCancelAttr.hpp" #include "ecflow/attribute/LateAttr.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Extract.hpp" #include "ecflow/core/Indentor.hpp" #include "ecflow/core/Log.hpp" @@ -1219,7 +1220,7 @@ search_user_edit_variables(const std::string& name, std::string& value, const Na bool Node::variableSubstitution(std::string& cmd) const { char micro = '%'; std::string micro_char; - findParentUserVariableValue(Str::ECF_MICRO(), micro_char); + findParentUserVariableValue(ecf::environment::ECF_MICRO, micro_char); if (!micro_char.empty() && micro_char.size() == 1) { micro = micro_char[0]; } @@ -1291,15 +1292,15 @@ bool Node::variable_substitution(std::string& cmd, const NameValueMap& user_edit // Leave ECF_JOB and ECF_JOBOUT out of this list: As user may legitimately override these. ECFLOW-999 bool generated_variable = false; if (percentVar.find("ECF_") == 0) { - if (percentVar.find(Str::ECF_HOST()) != std::string::npos) + if (percentVar.find(ecf::environment::ECF_HOST) != std::string::npos) generated_variable = true; - else if (percentVar.find(Str::ECF_PORT()) != std::string::npos) + else if (percentVar.find(ecf::environment::ECF_PORT) != std::string::npos) generated_variable = true; - else if (percentVar.find(Str::ECF_TRYNO()) != std::string::npos) + else if (percentVar.find(ecf::environment::ECF_TRYNO) != std::string::npos) generated_variable = true; - else if (percentVar.find(Str::ECF_NAME()) != std::string::npos) + else if (percentVar.find(ecf::environment::ECF_NAME) != std::string::npos) generated_variable = true; - else if (percentVar.find(Str::ECF_PASS()) != std::string::npos) + else if (percentVar.find(ecf::environment::ECF_PASS) != std::string::npos) generated_variable = true; } diff --git a/libs/node/src/ecflow/node/NodeContainer.cpp b/libs/node/src/ecflow/node/NodeContainer.cpp index 8363d3f3e..d10b4ecbc 100644 --- a/libs/node/src/ecflow/node/NodeContainer.cpp +++ b/libs/node/src/ecflow/node/NodeContainer.cpp @@ -19,6 +19,7 @@ #include "ecflow/core/Converter.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Host.hpp" #include "ecflow/core/Log.hpp" @@ -1135,7 +1136,7 @@ void NodeContainer::update_limits() { std::string NodeContainer::archive_path() const { std::string the_archive_path; - if (!findParentUserVariableValue(Str::ECF_HOME(), the_archive_path)) { + if (!findParentUserVariableValue(ecf::environment::ECF_HOME, the_archive_path)) { std::stringstream ss; ss << "NodeContainer::archive_path: cannot find ECF_HOME from " << debugNodePath(); throw std::runtime_error(ss.str()); @@ -1148,7 +1149,7 @@ std::string NodeContainer::archive_path() const { std::string port = Str::DEFAULT_PORT_NUMBER(); Defs* the_defs = defs(); if (the_defs) { - port = the_defs->server().find_variable(Str::ECF_PORT()); + port = the_defs->server().find_variable(ecf::environment::ECF_PORT); if (port.empty()) port = Str::DEFAULT_PORT_NUMBER(); } @@ -1308,7 +1309,7 @@ void NodeContainer::remove_archived_files() { } std::string ecf_home; - if (!findParentUserVariableValue(Str::ECF_HOME(), ecf_home)) { + if (!findParentUserVariableValue(ecf::environment::ECF_HOME, ecf_home)) { return; } diff --git a/libs/node/src/ecflow/node/ServerState.cpp b/libs/node/src/ecflow/node/ServerState.cpp index b3068f42d..6fc99f0f0 100644 --- a/libs/node/src/ecflow/node/ServerState.cpp +++ b/libs/node/src/ecflow/node/ServerState.cpp @@ -11,6 +11,7 @@ #include "ecflow/node/ServerState.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Host.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/Serialization.hpp" @@ -307,7 +308,7 @@ bool ServerState::variableSubsitution(std::string& cmd) const { // edit bill '%fred%' # should be 10 // To prevent this we will use a simple count char micro = '%'; - const Variable& micro_var = findVariable(Str::ECF_MICRO()); + const Variable& micro_var = findVariable(ecf::environment::ECF_MICRO); if (!micro_var.empty() && !micro_var.theValue().empty()) micro = micro_var.theValue()[0]; @@ -420,9 +421,9 @@ void ServerState::setup_default_env(const std::string& port) { void ServerState::setup_default_server_variables(std::vector& server_variables, const std::string& port) { Host host; - server_variables.emplace_back(Str::ECF_MICRO(), + server_variables.emplace_back(ecf::environment::ECF_MICRO, Ecf::MICRO()); // Preprocessor character for variable substitution and including files - server_variables.emplace_back(Str::ECF_HOME(), string(".")); + server_variables.emplace_back(ecf::environment::ECF_HOME, string(".")); server_variables.emplace_back(string("ECF_JOB_CMD"), Ecf::JOB_CMD()); // Command to be executed to submit a job server_variables.emplace_back(string("ECF_KILL_CMD"), Ecf::KILL_CMD()); // Command to be executed to kill a job server_variables.emplace_back(string("ECF_STATUS_CMD"), @@ -446,15 +447,15 @@ void ServerState::setup_default_server_variables(std::vector& server_v // job aborts, the job is automatically re-run. Useful when jobs are run in // an unreliable environments. For example using using commands like ftp(1) // in a job can fail easily, but re-running the job will often work - server_variables.emplace_back(Str::ECF_TRIES(), string("2")); + server_variables.emplace_back(ecf::environment::ECF_TRIES, string("2")); server_variables.emplace_back(string("ECF_VERSION"), Version::raw()); // server version // Needed to setup client environment. // The server sets these variable for use by the client. i.e when creating the jobs // The clients then uses them to communicate with the server. - server_variables.emplace_back(Str::ECF_PORT(), port); - server_variables.emplace_back(Str::ECF_HOST(), Str::LOCALHOST()); + server_variables.emplace_back(ecf::environment::ECF_PORT, port); + server_variables.emplace_back(ecf::environment::ECF_HOST, Str::LOCALHOST()); } /// determines why the node is not running. diff --git a/libs/node/src/ecflow/node/Submittable.cpp b/libs/node/src/ecflow/node/Submittable.cpp index 8f615b9db..8e878b4cf 100644 --- a/libs/node/src/ecflow/node/Submittable.cpp +++ b/libs/node/src/ecflow/node/Submittable.cpp @@ -15,6 +15,7 @@ #include "ecflow/core/Converter.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Extract.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Log.hpp" @@ -341,7 +342,7 @@ EcfFile Submittable::locatedEcfFile() const { std::string reasonEcfFileNotFound; std::string theAbsNodePath = absNodePath(); std::string ecf_home; - findParentUserVariableValue(Str::ECF_HOME(), ecf_home); + findParentUserVariableValue(ecf::environment::ECF_HOME, ecf_home); /// Update local ECF_SCRIPT variable, ECF_SCRIPT is a generated variable. IT *MUST* exist /// Likewise generated variable like TASK and ECF_NAME as they may occur in ECF_FETCH_CMD/ECF_SCRIPT_CMD @@ -368,7 +369,7 @@ EcfFile Submittable::locatedEcfFile() const { // Caution: This is not used in operations or research; equally it has not been tested. std::string ecf_fetch_cmd; - findParentVariableValue(Str::ECF_FETCH(), ecf_fetch_cmd); + findParentVariableValue(ecf::environment::ECF_FETCH, ecf_fetch_cmd); if (!ecf_fetch_cmd.empty()) { #ifdef DEBUG_TASK_LOCATION std::cout << "Submittable::locatedEcfFile() Submittable " << name() << " ECF_FETCH = '" << ecf_fetch_cmd @@ -417,7 +418,7 @@ EcfFile Submittable::locatedEcfFile() const { } std::string ecf_filesDirectory; - if (findParentUserVariableValue(Str::ECF_FILES(), ecf_filesDirectory)) { + if (findParentUserVariableValue(ecf::environment::ECF_FILES, ecf_filesDirectory)) { #ifdef DEBUG_TASK_LOCATION std::cout << "Submittable::locatedEcfFile() Submittable " << name() << " searching ECF_FILES = '" << ecf_filesDirectory << "' backwards\n"; @@ -570,7 +571,7 @@ bool Submittable::submit_job_only(JobsParam& jobsParam) { // If the task is a dummy task, return true std::string theValue; - if (findParentUserVariableValue(Str::ECF_DUMMY_TASK(), theValue)) { + if (findParentUserVariableValue(ecf::environment::ECF_DUMMY_TASK, theValue)) { return true; } @@ -585,7 +586,7 @@ bool Submittable::submit_job_only(JobsParam& jobsParam) { requeue_labels(); // ECFLOW-195, requeue no longer resets labels on tasks, hence we do it at task run time. theValue.clear(); - if (findParentUserVariableValue(Str::ECF_NO_SCRIPT(), theValue)) { + if (findParentUserVariableValue(ecf::environment::ECF_NO_SCRIPT, theValue)) { // The script is based on the ECF_JOB_CMD return non_script_based_job_submission(jobsParam); } @@ -795,7 +796,7 @@ void Submittable::kill(const std::string& zombie_pid) { throw std::runtime_error(ss.str()); } - if (!findParentUserVariableValue(Str::ECF_KILL_CMD(), ecf_kill_cmd) || ecf_kill_cmd.empty()) { + if (!findParentUserVariableValue(ecf::environment::ECF_KILL_CMD, ecf_kill_cmd) || ecf_kill_cmd.empty()) { flag().set(ecf::Flag::KILLCMD_FAILED); std::stringstream ss; ss << "Submittable::kill: ECF_KILL_CMD not defined, for task " << absNodePath() << "\n"; @@ -804,7 +805,7 @@ void Submittable::kill(const std::string& zombie_pid) { } else { // Use input - if (!findParentUserVariableValue(Str::ECF_KILL_CMD(), ecf_kill_cmd) || ecf_kill_cmd.empty()) { + if (!findParentUserVariableValue(ecf::environment::ECF_KILL_CMD, ecf_kill_cmd) || ecf_kill_cmd.empty()) { flag().set(ecf::Flag::KILLCMD_FAILED); std::stringstream ss; ss << "Submittable::kill: ECF_KILL_CMD not defined, for task " << absNodePath() << "\n"; @@ -870,7 +871,7 @@ void Submittable::status() { } std::string ecf_status_cmd; - if (!findParentUserVariableValue(Str::ECF_STATUS_CMD(), ecf_status_cmd) || ecf_status_cmd.empty()) { + if (!findParentUserVariableValue(ecf::environment::ECF_STATUS_CMD, ecf_status_cmd) || ecf_status_cmd.empty()) { flag().set(ecf::Flag::STATUSCMD_FAILED); std::stringstream ss; ss << "Submittable::status: ECF_STATUS_CMD not defined, for task " << absNodePath() << "\n"; @@ -901,7 +902,7 @@ bool Submittable::createChildProcess(JobsParam& jobsParam) { cout << "Submittable::createChildProcess for task " << name() << endl; #endif std::string ecf_job_cmd; - findParentUserVariableValue(Str::ECF_JOB_CMD(), ecf_job_cmd); + findParentUserVariableValue(ecf::environment::ECF_JOB_CMD, ecf_job_cmd); if (ecf_job_cmd.empty()) { jobsParam.errorMsg() += "Submittable::createChildProcess: Could not find ECF_JOB_CMD : "; return false; @@ -1070,21 +1071,21 @@ void Submittable::set_genvar_ecfrid(const std::string& value) { // Check the variable names. i.e. we know they are valid SubGenVariables::SubGenVariables(const Submittable* sub) : submittable_(sub), - genvar_ecfjob_(Str::ECF_JOB(), "", false), - genvar_ecfjobout_(Str::ECF_JOBOUT(), "", false), - genvar_ecftryno_(Str::ECF_TRYNO(), "", false), + genvar_ecfjob_(ecf::environment::ECF_JOB, "", false), + genvar_ecfjobout_(ecf::environment::ECF_JOBOUT, "", false), + genvar_ecftryno_(ecf::environment::ECF_TRYNO, "", false), genvar_task_("TASK", "", false), - genvar_ecfpass_(Str::ECF_PASS(), "", false), - genvar_ecfscript_(Str::ECF_SCRIPT(), "", false), - genvar_ecfname_(Str::ECF_NAME(), "", false), - genvar_ecfrid_(Str::ECF_RID(), "", false) { + genvar_ecfpass_(ecf::environment::ECF_PASS, "", false), + genvar_ecfscript_(ecf::environment::ECF_SCRIPT, "", false), + genvar_ecfname_(ecf::environment::ECF_NAME, "", false), + genvar_ecfrid_(ecf::environment::ECF_RID, "", false) { } void SubGenVariables::update_generated_variables() const { // cache strings that are used in many variables std::string theAbsNodePath = submittable_->absNodePath(); std::string ecf_home; - submittable_->findParentUserVariableValue(Str::ECF_HOME(), ecf_home); + submittable_->findParentUserVariableValue(ecf::environment::ECF_HOME, ecf_home); update_static_generated_variables(ecf_home, theAbsNodePath); update_dynamic_generated_variables(ecf_home, theAbsNodePath); } @@ -1129,7 +1130,7 @@ void SubGenVariables::update_dynamic_generated_variables(const std::string& ecf_ /// associated with Suites/Families nodes. /// Bottom up. Can be expensive when we have thousands of tasks. std::string ecf_out; - submittable_->findParentUserVariableValue(Str::ECF_OUT(), ecf_out); + submittable_->findParentUserVariableValue(ecf::environment::ECF_OUT, ecf_out); if (ecf_out.empty()) { genvar_ecfjobout_.value_by_ref().reserve(ecf_home.size() + theAbsNodePath.size() + 1 + the_try_no.size()); diff --git a/libs/node/src/ecflow/node/Task.cpp b/libs/node/src/ecflow/node/Task.cpp index ff15d6d2f..3797492d0 100644 --- a/libs/node/src/ecflow/node/Task.cpp +++ b/libs/node/src/ecflow/node/Task.cpp @@ -15,6 +15,7 @@ #include "ecflow/core/Converter.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Extract.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Indentor.hpp" @@ -214,7 +215,7 @@ alias_ptr Task::add_alias(std::vector& user_file_contents, throw std::runtime_error(ss.str()); } - findParentUserVariableValue(Str::ECF_HOME(), dir_to_create); + findParentUserVariableValue(ecf::environment::ECF_HOME, dir_to_create); dir_to_create += absNodePath(); if (!File::createDirectories(dir_to_create)) { throw std::runtime_error("Task::add_alias: could not create directory " + dir_to_create); @@ -519,7 +520,7 @@ bool Task::resolveDependencies(JobsParam& jobsParam) { // If the task was aborted, and we have not exceeded ECF_TRIES, then resubmit // otherwise ONLY in state QUEUED can we submit jobs std::string varValue; - if (findParentUserVariableValue(Str::ECF_TRIES(), varValue)) { + if (findParentUserVariableValue(ecf::environment::ECF_TRIES, varValue)) { // std::cout << "tryNo_ = " << tryNo_ << " ECF_TRIES = " << varValue << "\n"; try { auto ecf_tries = ecf::convert_to(varValue); @@ -816,7 +817,7 @@ const std::string& Task::script_extension() const { // Migration support, allow user to specify extension. This allows users to use '.sms' // Note: This should be removed in the future since there is performance hit. // searching up the node tree, when most of the time we are using .ecf - const std::string& ecf_extn = find_parent_user_variable_value(Str::ECF_EXTN()); + const std::string& ecf_extn = find_parent_user_variable_value(ecf::environment::ECF_EXTN); if (!ecf_extn.empty()) return ecf_extn; return File::ECF_EXTN(); // ".ecf" diff --git a/libs/node/src/ecflow/node/TaskScriptGenerator.cpp b/libs/node/src/ecflow/node/TaskScriptGenerator.cpp index 6199a0d5a..eeb012f70 100644 --- a/libs/node/src/ecflow/node/TaskScriptGenerator.cpp +++ b/libs/node/src/ecflow/node/TaskScriptGenerator.cpp @@ -15,6 +15,7 @@ #include "ecflow/attribute/QueueAttr.hpp" #include "ecflow/core/Converter.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Task.hpp" @@ -27,12 +28,12 @@ namespace ecf { TaskScriptGenerator::TaskScriptGenerator(const Task* task) : task_(task), is_dummy_task_(false) { /// if ECF_DUMMY_TASK specified ignore std::string theValue; - is_dummy_task_ = task_->findParentUserVariableValue(Str::ECF_DUMMY_TASK(), theValue); + is_dummy_task_ = task_->findParentUserVariableValue(ecf::environment::ECF_DUMMY_TASK, theValue); if (is_dummy_task_) return; /// if ECF_FILES specified use this before ECF_HOME - if (task_->findParentUserVariableValue(Str::ECF_FILES(), ecf_files_)) { + if (task_->findParentUserVariableValue(ecf::environment::ECF_FILES, ecf_files_)) { // Create any missing directories if ECF_FILES is specified try { fs::create_directories(ecf_files_); @@ -45,13 +46,13 @@ TaskScriptGenerator::TaskScriptGenerator(const Task* task) : task_(task), is_dum } /// Find ECF_HOME and ECF_INCLUDE - if (!task_->findParentUserVariableValue(Str::ECF_HOME(), ecf_home_)) { + if (!task_->findParentUserVariableValue(ecf::environment::ECF_HOME, ecf_home_)) { std::stringstream ss; ss << "TaskScriptGenerator: Could not generate scripts for task " << task_->absNodePath() << " no ECF_HOME specified\n"; throw std::runtime_error(ss.str()); } - if (!task_->findParentUserVariableValue(Str::ECF_INCLUDE(), ecf_include_)) { + if (!task_->findParentUserVariableValue(ecf::environment::ECF_INCLUDE, ecf_include_)) { std::stringstream ss; ss << "TaskScriptGenerator: Could not generate scripts for task " << task_->absNodePath() << " no ECF_INCLUDE specified\n"; diff --git a/libs/node/test/TestAlias.cpp b/libs/node/test/TestAlias.cpp index 1bf3ac50e..769439dea 100644 --- a/libs/node/test/TestAlias.cpp +++ b/libs/node/test/TestAlias.cpp @@ -12,6 +12,7 @@ #include +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Alias.hpp" @@ -56,7 +57,7 @@ BOOST_AUTO_TEST_CASE(test_alias_create) { t->addEvent(event2); t->addLabel(label1); t->addLabel(label2); - s->add_variable(Str::ECF_HOME(), ecf_home); + s->add_variable(ecf::environment::ECF_HOME, ecf_home); } // Create .usr file content diff --git a/libs/node/test/TestEcfFile.cpp b/libs/node/test/TestEcfFile.cpp index ea483d757..469884316 100644 --- a/libs/node/test/TestEcfFile.cpp +++ b/libs/node/test/TestEcfFile.cpp @@ -15,6 +15,7 @@ #include #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Pid.hpp" #include "ecflow/core/Str.hpp" @@ -29,6 +30,10 @@ using namespace std; using namespace ecf; +boost::test_tools::assertion_result is_testing_on_cray([[maybe_unused]] boost::unit_test::test_unit_id id) { + return ecf::environment::has_environment_variable("ECFLOW_CRAY_BATCH"); +} + BOOST_AUTO_TEST_SUITE(U_Node) BOOST_AUTO_TEST_SUITE(T_EcfFile) @@ -68,7 +73,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_include_file) { cout << "ANode:: ...test_ecf_simple_include_file"; // This test FAIL's randomly on the cray in BATCH mode, but passes in interactive mode. - if (getenv("ECFLOW_CRAY_BATCH")) { + if (auto var = getenv("ECFLOW_CRAY_BATCH"); var) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -85,7 +90,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_include_file) { suite_ptr suite = Suite::create(Pid::unique_name("test_ecf_simple_include_file")); Defs theDefs; { - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addTask(task_t1); theDefs.addSuite(suite); } @@ -93,7 +98,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_include_file) { // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE std::string ecf_home = File::test_data("libs/node/test/data", "libs/node"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -164,7 +169,7 @@ BOOST_AUTO_TEST_CASE(test_ECFLOW_495) { // endsuite Defs theDefs; suite_ptr suite = theDefs.add_suite(Pid::unique_name("test_ECFLOW_495")); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); task_ptr task_t1 = suite->add_task("t1"); // PrintStyle style(PrintStyle::STATE); @@ -173,7 +178,7 @@ BOOST_AUTO_TEST_CASE(test_ECFLOW_495) { // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE std::string ecf_home = File::test_data("libs/node/test/data", "libs/node"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the ecf files @@ -241,7 +246,7 @@ BOOST_AUTO_TEST_CASE(test_ECF_SCRIPT_CMD_ECFLOW_427) { suite_ptr suite = Suite::create(Pid::unique_name("test_ECF_SCRIPT_CMD_ECFLOW_427")); Defs theDefs; { - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addVariable(Variable("body", "body")); suite->addTask(task_t1); theDefs.addSuite(suite); @@ -250,7 +255,7 @@ BOOST_AUTO_TEST_CASE(test_ECF_SCRIPT_CMD_ECFLOW_427) { // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE std::string ecf_home = File::test_data("libs/node/test/data", "libs/node"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -392,7 +397,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_include_file) { suite_ptr suite = Suite::create(Pid::unique_name("test_ecf_include_file")); Defs theDefs; { - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addVariable(Variable("SLEEPTIME", "1")); suite->addVariable(Variable("ECF_CLIENT_EXE_PATH", "a/made/up/path")); suite->addTask(task_t1); @@ -401,7 +406,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_include_file) { // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -475,7 +480,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_include_multi_paths_ECFLOW_261) { Defs theDefs; { suite->addVariable( - Variable(Str::ECF_INCLUDE(), + Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/empty_include1:$ECF_HOME/empty_include2:$ECF_HOME/includes:$ECF_HOME/includes2")); suite->addTask(task_t1); theDefs.addSuite(suite); @@ -483,7 +488,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_include_multi_paths_ECFLOW_261) { // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -557,14 +562,14 @@ BOOST_AUTO_TEST_CASE(test_ecf_include_ECFLOW_274) { suite_ptr suite = Suite::create(Pid::unique_name("test_ecf_include_ECFLOW_274")); Defs theDefs; { - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addTask(task_t1); theDefs.addSuite(suite); } // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -650,7 +655,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_used_variables) { Defs theDefs; { suite = theDefs.add_suite(Pid::unique_name("test_ecf_simple_used_variables")); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->add_variable("ESUITE", "suite"); task_t1 = suite->add_family("f1")->add_task("t1"); } @@ -658,7 +663,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_used_variables) { // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE std::string ecf_home = File::test_data("libs/node/test/data", "libs/node"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -725,7 +730,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_used_variables_with_comments) { Defs theDefs; { suite = theDefs.add_suite(Pid::unique_name("test_ecf_simple_used_variables_with_comments")); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->add_variable("ETASK", "suite"); suite->add_variable("FRED", "fred"); task_t1 = suite->add_family("f1")->add_task("t1"); @@ -733,7 +738,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_used_variables_with_comments) { // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -796,14 +801,14 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_used_variables_errors) { Defs theDefs; { suite = theDefs.add_suite(Pid::unique_name("test_ecf_simple_used_variables_errors")); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->add_variable("ETASK", "suite"); task_t1 = suite->add_family("f1")->add_task("t1"); } // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -866,7 +871,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file) { suite_ptr suite = Suite::create(Pid::unique_name("test_ecf_file")); Defs theDefs; { - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addVariable(Variable("SLEEPTIME", "1")); suite->addVariable(Variable("ECF_CLIENT_EXE_PATH", "a/made/up/path")); for (const NameValueMap::value_type& p : expected_used_variables) { @@ -877,7 +882,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file) { } // Override ECF_HOME. ECF_HOME is need to locate to the .ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -1050,7 +1055,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_includenoop) { suite_ptr suite = Suite::create(Pid::unique_name("test_ecf_file_includenoop")); Defs theDefs; { - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addVariable(Variable("SLEEPTIME", "1")); suite->addVariable(Variable("ECF_CLIENT_EXE_PATH", "a/made/up/path")); suite->addTask(task_t1); @@ -1059,7 +1064,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_includenoop) { // cout << theDefs << "\n"; // Override ECF_HOME. ECF_HOME is need to locate to the .ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the ecf files @@ -1148,7 +1153,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_override_ECF_JOB) { suite_ptr suite = Suite::create(Pid::unique_name("test_ecf_file_override_ECF_JOB")); Defs theDefs; { - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addVariable(Variable("SLEEPTIME", "1")); suite->addVariable(Variable("ECF_CLIENT_EXE_PATH", "a/made/up/path")); suite->addTask(task_t1); @@ -1157,7 +1162,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_override_ECF_JOB) { // cout << theDefs << "\n"; // Override ECF_HOME. ECF_HOME is need to locate to the .ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the ecf files @@ -1224,13 +1229,13 @@ BOOST_AUTO_TEST_CASE(test_manual_files) { // Create a defs file, where the task name mirrors the ecf files in the given directory Defs theDefs; suite_ptr suite = theDefs.add_suite("suite"); // ** relies on name of suite, in SMSHOME/suite - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/../includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/../includes")); family_ptr family = suite->add_family("family"); task_ptr task_t1 = family->add_task("t1"); // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -1311,13 +1316,13 @@ BOOST_AUTO_TEST_CASE(test_ECFLOW_672) { // endsuite Defs theDefs; suite_ptr suite = theDefs.add_suite("ECFLOW_672"); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/ECFLOW_672")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/ECFLOW_672")); task_ptr task_t1 = suite->add_task("t"); // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE std::string ecf_home = File::test_data("libs/node/test/data", "libs/node"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the ecf files @@ -1371,7 +1376,7 @@ static void basic_test_template(const std::string& test_name, suite_ptr suite = Suite::create(Pid::unique_name(test_name)); Defs theDefs; { - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->add_variable("simple", "simple"); suite->add_variable("tail", "tail"); if (!ecf_micro.empty()) @@ -1383,7 +1388,7 @@ static void basic_test_template(const std::string& test_name, // Override ECF_HOME. ECF_HOME is as default location for .ecf files, when ECF_INCLUDE not specified // or when file does not exist in ECF_INCLUDE std::string ecf_home = File::test_data("libs/node/test/data", "libs/node"); - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files diff --git a/libs/node/test/TestEcfFileLocator.cpp b/libs/node/test/TestEcfFileLocator.cpp index cec4861c5..3cb9c1b83 100644 --- a/libs/node/test/TestEcfFileLocator.cpp +++ b/libs/node/test/TestEcfFileLocator.cpp @@ -12,6 +12,7 @@ #include +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Pid.hpp" #include "ecflow/core/Str.hpp" @@ -111,7 +112,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_search) { // task task Defs theDefs; suite_ptr suite = theDefs.add_suite(Pid::unique_name("test_ecf_file_search")); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); family_ptr f1 = suite->add_family("f1"); family_ptr f2 = f1->add_family("f2"); family_ptr f3 = f2->add_family("f3"); @@ -121,7 +122,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_search) { // or when file does not exist in ECF_INCLUDE std::string ecf_home = File::test_data("libs/node/test/data", "libs/node"); std::string ecf_lists = File::test_data("libs/node/test/data", "libs/node"); - suite->add_variable(Str::ECF_HOME(), ecf_home); + suite->add_variable(ecf::environment::ECF_HOME, ecf_home); // cerr << theDefs << "\n"; /// begin , will cause creation of generated variables. The generated variables @@ -142,7 +143,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_search) { suite->deleteVariable("ECF_FILES_LOOKUP"); // cleanup - suite->add_variable(Str::ECF_FILES(), ecf_lists); + suite->add_variable(ecf::environment::ECF_FILES, ecf_lists); located_ecf_file(task, EcfFile::ECF_SCRIPT, EcfFile::PRUNE_ROOT, @@ -168,7 +169,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_search) { suite->deleteVariable("ECF_FILES_LOOKUP"); // cleanup - suite->add_variable(Str::ECF_FILES(), ecf_lists); + suite->add_variable(ecf::environment::ECF_FILES, ecf_lists); located_ecf_file(task, EcfFile::ECF_FILES, EcfFile::PRUNE_ROOT, __LINE__); suite->add_variable("ECF_FILES_LOOKUP", "prune_leaf"); // change look up method located_ecf_file(task, EcfFile::ECF_FILES, EcfFile::PRUNE_LEAF, __LINE__); @@ -207,7 +208,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_search) { } { // cout << "Test ECF_FILES at intermediate location, by prune_leaf\n"; - suite->add_variable(Str::ECF_FILES(), ecf_lists); + suite->add_variable(ecf::environment::ECF_FILES, ecf_lists); Node* node = task.get(); node = node->parent(); node = node->parent(); @@ -281,7 +282,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_locator) { Defs theDefs; { suite_ptr suite = theDefs.add_suite("suite"); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addVariable(Variable("SLEEPTIME", "10")); family_ptr fam = suite->add_family("family"); fam->add_task("t1"); @@ -297,16 +298,16 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_locator) { } { suite_ptr suite2 = theDefs.add_suite("suite2"); - suite2->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); - suite2->addVariable(Variable(Str::ECF_FILES(), "$ECF_HOME")); + suite2->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); + suite2->addVariable(Variable(ecf::environment::ECF_FILES, "$ECF_HOME")); family_ptr fam = suite2->add_family("family"); - fam->addVariable(Variable(Str::ECF_FETCH(), "smsfetch -F %ECF_FILES% -I %ECF_INCLUDE%")); + fam->addVariable(Variable(ecf::environment::ECF_FETCH, "smsfetch -F %ECF_FILES% -I %ECF_INCLUDE%")); fam->add_task("t2"); } { suite_ptr suite = theDefs.add_suite("suite3"); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); - suite->addVariable(Variable(Str::ECF_FILES(), "$ECF_HOME")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_FILES, "$ECF_HOME")); family_ptr fam = suite->add_family("family"); fam->addVariable(Variable("ECF_SCRIPT_CMD", "script_cmd -F %ECF_FILES% -I %ECF_INCLUDE%")); fam->add_task("t2"); @@ -319,7 +320,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_locator) { BOOST_REQUIRE_MESSAGE(theTasks.size() == 8, "Expected 8 tasks but found, " << theTasks.size()); // Override ECF_HOME. ECF_HOME is need to locate to the ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), smshome); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, smshome); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the sms files @@ -381,7 +382,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_locator_using_ECF_FILES) { Defs theDefs; { suite_ptr suite = theDefs.add_suite("suite"); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addVariable(Variable("SLEEPTIME", "10")); family_ptr fam = suite->add_family("family"); fam->add_task("t1"); @@ -395,8 +396,8 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_locator_using_ECF_FILES) { BOOST_REQUIRE_MESSAGE(theTasks.size() == 3, "Expected 3 tasks but found, " << theTasks.size()); // ECF_HOME, a directory with no .ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), smshome); - theDefs.set_server().add_or_update_user_variables(Str::ECF_FILES(), ecf_files); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, smshome); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_FILES, ecf_files); // cerr << theDefs << "\n"; @@ -448,7 +449,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_locator_using_ECF_FILES_variable_substitution Defs theDefs; { suite_ptr suite = theDefs.add_suite("suite"); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); suite->addVariable(Variable("SLEEPTIME", "10")); family_ptr fam = suite->add_family("family"); fam->addVariable(Variable("FAMILY", "family")); @@ -463,8 +464,8 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_locator_using_ECF_FILES_variable_substitution BOOST_REQUIRE_MESSAGE(theTasks.size() == 3, "Expected 3 tasks but found, " << theTasks.size()); // ECF_HOME, a directory with no .ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), smshome); - theDefs.set_server().add_or_update_user_variables(Str::ECF_FILES(), ecf_files); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, smshome); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_FILES, ecf_files); // cerr << theDefs << "\n"; diff --git a/libs/node/test/TestEnviromentSubstitution.cpp b/libs/node/test/TestEnviromentSubstitution.cpp index 4d8421c11..ba0d5a24e 100644 --- a/libs/node/test/TestEnviromentSubstitution.cpp +++ b/libs/node/test/TestEnviromentSubstitution.cpp @@ -13,6 +13,7 @@ #include +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Suite.hpp" @@ -35,7 +36,7 @@ BOOST_AUTO_TEST_CASE(test_environment_substitution) { suite->addVariable(Variable("AVI", "avi")); std::vector> env; - env.emplace_back(Str::ECF_HOME(), string("/home/smshome")); + env.emplace_back(ecf::environment::ECF_HOME, string("/home/smshome")); env.emplace_back(string("FRED"), string("/home/fred")); env.emplace_back(string("BILL"), string("/home/bill")); env.emplace_back(string("JANE"), string("/home/jane")); diff --git a/libs/node/test/TestJobCreator.cpp b/libs/node/test/TestJobCreator.cpp index 8069c5a13..595efcbea 100644 --- a/libs/node/test/TestJobCreator.cpp +++ b/libs/node/test/TestJobCreator.cpp @@ -12,6 +12,7 @@ #include +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -63,7 +64,7 @@ BOOST_AUTO_TEST_CASE(test_job_creator) { { suite_ptr suite = Suite::create("suite"); family_ptr fam = Family::create("family"); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/../includes")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/../includes")); suite->addVariable(Variable("SLEEPTIME", "1")); suite->addVariable(Variable("ECF_CLIENT_EXE_PATH", "a/made/up/path")); fam->addTask(Task::create("t1")); @@ -89,7 +90,7 @@ BOOST_AUTO_TEST_CASE(test_job_creator) { BOOST_REQUIRE_MESSAGE(theTasks.size() == 6, "Expected 6 tasks but found, " << theTasks.size()); // Override ECF_HOME. ECF_HOME is need to locate to the .ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the ecf files diff --git a/libs/node/test/TestJobProfiler.cpp b/libs/node/test/TestJobProfiler.cpp index 1f7d3593b..30b4dc5e3 100644 --- a/libs/node/test/TestJobProfiler.cpp +++ b/libs/node/test/TestJobProfiler.cpp @@ -12,6 +12,7 @@ #include +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/Str.hpp" @@ -45,8 +46,10 @@ BOOST_AUTO_TEST_CASE(test_job_profiler) { Defs theDefs; { suite_ptr suite = theDefs.add_suite("suite"); - suite->addVariable(Variable(Str::ECF_INCLUDE(), File::test_data("libs/node/test/data/includes", "libs/node"))); - suite->addVariable(Variable("ECF_HOME", File::test_data("libs/node/test/data/SMSHOME", "libs/node"))); + suite->addVariable( + Variable(ecf::environment::ECF_INCLUDE, File::test_data("libs/node/test/data/includes", "libs/node"))); + suite->addVariable( + Variable(ecf::environment::ECF_HOME, File::test_data("libs/node/test/data/SMSHOME", "libs/node"))); suite->addVariable(Variable("SLEEPTIME", "10")); family_ptr fam = suite->add_family("family"); fam->add_task("t1"); diff --git a/libs/node/test/TestPreProcessing.cpp b/libs/node/test/TestPreProcessing.cpp index 2ec8afb1d..d79f7d300 100644 --- a/libs/node/test/TestPreProcessing.cpp +++ b/libs/node/test/TestPreProcessing.cpp @@ -14,6 +14,7 @@ #include #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -119,8 +120,8 @@ void test_sms_preprocessing(const std::string& directory, bool pass) { Defs theDefs; { suite_ptr suite = theDefs.add_suite("suite"); - suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/includes")); - suite->addVariable(Variable(Str::ECF_OUT(), "$ECF_HOME")); + suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/includes")); + suite->addVariable(Variable(ecf::environment::ECF_OUT, "$ECF_HOME")); suite->addVariable(Variable("SLEEPTIME", "10")); family_ptr fam = suite->add_family("family"); @@ -163,7 +164,7 @@ void test_sms_preprocessing(const std::string& directory, bool pass) { theDefs.getAllTasks(theTasks); // Override ECF_HOME. ECF_HOME is need to locate the ecf files - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + theDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are used in client scripts(sms) and used to locate the sms files diff --git a/libs/node/test/TestReplace.cpp b/libs/node/test/TestReplace.cpp index 51663b9e0..5550dc895 100644 --- a/libs/node/test/TestReplace.cpp +++ b/libs/node/test/TestReplace.cpp @@ -11,6 +11,7 @@ #include #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -958,7 +959,7 @@ BOOST_AUTO_TEST_CASE(test_trigger_references_during_replace) { suite_ptr server_suite; { server_suite = serverDefs.add_suite("suite"); - server_suite->addVariable(Variable(Str::ECF_INCLUDE(), "$ECF_HOME/../includes")); + server_suite->addVariable(Variable(ecf::environment::ECF_INCLUDE, "$ECF_HOME/../includes")); server_suite->addVariable(Variable("SLEEPTIME", "1")); server_suite->addVariable(Variable("ECF_CLIENT_EXE_PATH", "a/made/up/path")); family_ptr fam = server_suite->add_family("family"); @@ -977,7 +978,7 @@ BOOST_AUTO_TEST_CASE(test_trigger_references_during_replace) { // Override ECF_HOME. ECF_HOME is need to locate to the .ecf files std::string ecf_home = File::test_data("libs/node/test/data/SMSHOME", "libs/node"); - serverDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), ecf_home); + serverDefs.set_server().add_or_update_user_variables(ecf::environment::ECF_HOME, ecf_home); /// begin , will cause creation of generated variables. The generated variables /// are use in client scripts and used to locate the ecf files diff --git a/libs/node/test/TestTaskScriptGenerator.cpp b/libs/node/test/TestTaskScriptGenerator.cpp index eca8b9a16..806953328 100644 --- a/libs/node/test/TestTaskScriptGenerator.cpp +++ b/libs/node/test/TestTaskScriptGenerator.cpp @@ -15,6 +15,7 @@ #include "MyDefsFixture.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -92,8 +93,8 @@ BOOST_AUTO_TEST_CASE(test_task_script_generator) { Defs theDefs; { suite_ptr suite = theDefs.add_suite("suite"); - suite->add_variable(Str::ECF_INCLUDE(), ecf_home); - suite->add_variable(Str::ECF_HOME(), ecf_home); + suite->add_variable(ecf::environment::ECF_INCLUDE, ecf_home); + suite->add_variable(ecf::environment::ECF_HOME, ecf_home); suite->add_variable("SLEEP", "10"); task_ptr t1 = suite->add_task("t1"); t1->addEvent(Event("event1")); @@ -184,8 +185,8 @@ BOOST_AUTO_TEST_CASE(test_task_script_generator_with_dummy_tasks) { Defs theDefs; { suite_ptr suite = theDefs.add_suite("suite"); - suite->add_variable(Str::ECF_INCLUDE(), ecf_home); - suite->add_variable(Str::ECF_HOME(), ecf_home); + suite->add_variable(ecf::environment::ECF_INCLUDE, ecf_home); + suite->add_variable(ecf::environment::ECF_HOME, ecf_home); suite->add_variable("SLEEP", "10"); family_ptr f1 = suite->add_family("f1"); tasks_with_scripts.push_back(f1->add_task("t1")); diff --git a/libs/node/test/TestVariableGeneration.cpp b/libs/node/test/TestVariableGeneration.cpp index f0f2ec20b..b27d4e1e1 100644 --- a/libs/node/test/TestVariableGeneration.cpp +++ b/libs/node/test/TestVariableGeneration.cpp @@ -14,6 +14,7 @@ #include "ecflow/core/Cal.hpp" #include "ecflow/core/Converter.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Family.hpp" @@ -66,13 +67,13 @@ BOOST_AUTO_TEST_CASE(test_generated_variables) { // Check Submittable generated variables findParentVariableValue(t, "TASK", "t"); - findParentVariableValue(t, Str::ECF_RID(), ""); - findParentVariableValue(t, Str::ECF_TRYNO(), "0"); - findParentVariableValue(t, Str::ECF_NAME(), "/suite/f/f2/t"); - findParentVariableValue(t, Str::ECF_PASS(), ""); - findParentVariableValue(t, Str::ECF_JOB(), "./suite/f/f2/t.job0"); - findParentVariableValue(t, Str::ECF_JOBOUT(), "./suite/f/f2/t.0"); - findParentVariableValue(t, Str::ECF_SCRIPT(), "./suite/f/f2/t.ecf"); + findParentVariableValue(t, ecf::environment::ECF_RID, ""); + findParentVariableValue(t, ecf::environment::ECF_TRYNO, "0"); + findParentVariableValue(t, ecf::environment::ECF_NAME, "/suite/f/f2/t"); + findParentVariableValue(t, ecf::environment::ECF_PASS, ""); + findParentVariableValue(t, ecf::environment::ECF_JOB, "./suite/f/f2/t.job0"); + findParentVariableValue(t, ecf::environment::ECF_JOBOUT, "./suite/f/f2/t.0"); + findParentVariableValue(t, ecf::environment::ECF_SCRIPT, "./suite/f/f2/t.ecf"); // Check Family generated variables findParentVariableValue(t, "FAMILY", "f/f2"); diff --git a/libs/node/test/TestVariableSubstitution.cpp b/libs/node/test/TestVariableSubstitution.cpp index 14fe7acea..4874177d6 100644 --- a/libs/node/test/TestVariableSubstitution.cpp +++ b/libs/node/test/TestVariableSubstitution.cpp @@ -14,6 +14,7 @@ #include #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/core/Version.hpp" #include "ecflow/node/Defs.hpp" @@ -379,10 +380,10 @@ BOOST_AUTO_TEST_CASE(test_user_variable_substitution_1) { static std::vector required_server_variables() { std::vector required_server_variables; - required_server_variables.push_back(Str::ECF_PORT()); - required_server_variables.push_back(Str::ECF_HOST()); + required_server_variables.push_back(ecf::environment::ECF_PORT); + required_server_variables.push_back(ecf::environment::ECF_HOST); - required_server_variables.push_back(Str::ECF_HOME()); + required_server_variables.push_back(ecf::environment::ECF_HOME); required_server_variables.emplace_back("ECF_LOG"); required_server_variables.emplace_back("ECF_CHECK"); required_server_variables.emplace_back("ECF_CHECKOLD"); @@ -471,12 +472,12 @@ BOOST_AUTO_TEST_CASE(test_generated_variable_substitution) { string value; value.clear(); - t->findParentVariableValue(Str::ECF_JOBOUT(), value); + t->findParentVariableValue(ecf::environment::ECF_JOBOUT, value); BOOST_CHECK_MESSAGE(value == "/fred/bill/joe/suite/f/t.0", "ECF_JOBOUT expected /fred/bill/joe/suite/f/t.0, but found " << value); value.clear(); - t1->findParentVariableValue(Str::ECF_JOBOUT(), value); + t1->findParentVariableValue(ecf::environment::ECF_JOBOUT, value); BOOST_CHECK_MESSAGE(value == "/fred/bill/joe2/suite/f1/t1.0", "ECF_JOBOUT expected /fred/bill/joe/suite/f/t.0, but found " << value); diff --git a/libs/rest/src/ecflow/http/Client.cpp b/libs/rest/src/ecflow/http/Client.cpp index cd7661bb1..aa9697d9f 100644 --- a/libs/rest/src/ecflow/http/Client.cpp +++ b/libs/rest/src/ecflow/http/Client.cpp @@ -13,6 +13,7 @@ #include #include "ecflow/core/Child.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/http/BasicAuth.hpp" #include "ecflow/http/HttpServerException.hpp" @@ -26,8 +27,8 @@ namespace ecf::http { -const char* const ECF_USER = getenv("ECF_USER"); -const char* const ECF_PASS = getenv("ECF_PASS"); +const char* const ECF_USER = getenv(ecf::environment::ECF_USER); +const char* const ECF_PASS = getenv(ecf::environment::ECF_PASS); bool authenticate(const httplib::Request& request, ClientInvoker* ci) { diff --git a/libs/rest/src/ecflow/http/HttpServer.cpp b/libs/rest/src/ecflow/http/HttpServer.cpp index 4460bc6db..c528f8c58 100644 --- a/libs/rest/src/ecflow/http/HttpServer.cpp +++ b/libs/rest/src/ecflow/http/HttpServer.cpp @@ -13,6 +13,7 @@ #include #include "ecflow/core/Converter.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Filesystem.hpp" #include "ecflow/http/Api.hpp" #include "ecflow/http/JSON.hpp" @@ -25,33 +26,16 @@ HttpServer::HttpServer(int argc, char** argv) { } void read_environment() { - if (getenv("ECF_RESTAPI_VERBOSE") != nullptr) { - opts.verbose = true; - } - if (getenv("ECF_RESTAPI_NOSSL") != nullptr) { - opts.no_ssl = true; - } - if (getenv("ECF_RESTAPI_POLLING_INTERVAL") != nullptr) { - opts.polling_interval = atoi(getenv("ECF_RESTAPI_POLLING_INTERVAL")); - } - if (getenv("ECF_RESTAPI_PORT") != nullptr) { - opts.port = atoi(getenv("ECF_RESTAPI_PORT")); - } - if (getenv("ECF_HOST") != nullptr) { - opts.ecflow_host = std::string(getenv("ECF_HOST")); - } - if (getenv("ECF_PORT") != nullptr) { - opts.ecflow_port = atoi(getenv("ECF_PORT")); - } - if (getenv("ECF_RESTAPI_TOKENS_FILE") != nullptr) { - opts.tokens_file = std::string(getenv("ECF_RESTAPI_TOKENS_FILE")); - } - if (getenv("ECF_RESTAPI_CERT_DIRECTORY") != nullptr) { - opts.cert_directory = std::string(getenv("ECF_RESTAPI_CERT_DIRECTORY")); - } - if (getenv("ECF_RESTAPI_MAX_UPDATE_INTERVAL") != nullptr) { - opts.max_polling_interval = atoi(getenv("ECF_RESTAPI_MAX_UPDATE_INTERVAL")); - } + ecf::environment::get_environment_variable("ECF_RESTAPI_VERBOSE", opts.verbose); + ecf::environment::get_environment_variable("ECF_RESTAPI_NOSSL", opts.no_ssl); + ecf::environment::get_environment_variable("ECF_RESTAPI_POLLING_INTERVAL", opts.polling_interval); + ecf::environment::get_environment_variable("ECF_RESTAPI_PORT", opts.port); + ecf::environment::get_environment_variable("ECF_HOST", opts.ecflow_host); + ecf::environment::get_environment_variable("ECF_PORT", opts.ecflow_port); + ecf::environment::get_environment_variable("ECF_RESTAPI_TOKENS_FILE", opts.tokens_file); + ecf::environment::get_environment_variable("ECF_RESTAPI_CERT_DIRECTORY", opts.cert_directory); + ecf::environment::get_environment_variable("ECF_RESTAPI_MAX_UPDATE_INTERVAL", opts.max_polling_interval); + ecf::environment::get_environment_variable("ECF_HOST_PROTOCOL", opts.host_protocol); } void HttpServer::parse_args(int argc, char** argv) const { @@ -68,6 +52,7 @@ void HttpServer::parse_args(int argc, char** argv) const { bool verbose = false; bool no_ssl = false; + bool backend_http = false; desc.add_options() ("cert_directory", po::value(&opts.cert_directory), "directory where certificates are found (default: $HOME/.ecflowrc/ssl)") @@ -79,7 +64,8 @@ void HttpServer::parse_args(int argc, char** argv) const { ("port,p", po::value(&opts.port), "port to listen (default: 8080)") ("polling_interval", po::value(&opts.polling_interval), "interval in seconds to poll ecflow server for updates (default: 10)") ("tokens_file", po::value(&opts.tokens_file), "location of api tokens file (default: api-tokens.json)") - ("verbose,v", po::bool_switch(&verbose), "enable verbose mode"); + ("verbose,v", po::bool_switch(&verbose), "enable verbose mode") + ("http", po::bool_switch(&backend_http), "use http as protocol to communicate with server (default: false)"); // clang-format on @@ -97,9 +83,13 @@ void HttpServer::parse_args(int argc, char** argv) const { if (no_ssl) { opts.no_ssl = true; } + if (backend_http) { + opts.host_protocol = "http"; + } setenv("ECF_HOST", opts.ecflow_host.c_str(), 1); setenv("ECF_PORT", ecf::convert_to(opts.ecflow_port).c_str(), 1); + setenv("ECF_HOST_PROTOCOL", opts.host_protocol.c_str(), 1); // Unset these, otherwise ClientInvoker will automatically // try to use them unsetenv("ECF_PASSWD"); diff --git a/libs/rest/src/ecflow/http/Options.hpp b/libs/rest/src/ecflow/http/Options.hpp index 57e3f4bfe..3e03353a1 100644 --- a/libs/rest/src/ecflow/http/Options.hpp +++ b/libs/rest/src/ecflow/http/Options.hpp @@ -23,6 +23,7 @@ struct Options int port{8080}; // ECF_RESTAPI_PORT std::string ecflow_host{"localhost"}; // ECF_HOST int ecflow_port{3141}; // ECF_PORT + std::string host_protocol{""}; // ECF_HOST_PROTOCOL std::string tokens_file{"api-tokens.json"}; // ECF_RESTAPI_TOKENS_FILE std::string cert_directory{std::string(getenv("HOME")) + "/.ecflowrc/ssl"}; // ECF_RESTAPI_CERT_DIRECTORY int max_polling_interval{300}; // ECF_RESTAPI_MAX_POLLING_INTERVAL diff --git a/libs/rest/test/InvokeServer.hpp b/libs/rest/test/InvokeServer.hpp index c5e3a683d..fd16ad48c 100644 --- a/libs/rest/test/InvokeServer.hpp +++ b/libs/rest/test/InvokeServer.hpp @@ -19,6 +19,7 @@ #include "TestHelper.hpp" #include "ecflow/client/ClientInvoker.hpp" #include "ecflow/core/EcfPortLock.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Host.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/server/Server.hpp" @@ -27,7 +28,8 @@ class InvokeServer { public: InvokeServer() { - std::string port(getenv("ECF_PORT")); + std::string port; + ecf::environment::get_environment_variable(ecf::environment::ECF_PORT, port); /// Remove check pt and backup check pt file, else server will load it & remove log file ecf::Host h; fs::remove(h.ecf_checkpt_file(port)); @@ -58,7 +60,8 @@ class InvokeServer { } ~InvokeServer() { - std::string port(getenv("ECF_PORT")); + std::string port; + ecf::environment::get_environment_variable(ecf::environment::ECF_PORT, port); BOOST_TEST_MESSAGE("*****InvokeServer:: Closing server on port " << port); { diff --git a/libs/server/src/ecflow/server/ServerEnvironment.cpp b/libs/server/src/ecflow/server/ServerEnvironment.cpp index a0cf6bde8..a7454da9f 100644 --- a/libs/server/src/ecflow/server/ServerEnvironment.cpp +++ b/libs/server/src/ecflow/server/ServerEnvironment.cpp @@ -18,6 +18,7 @@ #include "ecflow/core/Calendar.hpp" #include "ecflow/core/Converter.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Filesystem.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/Pid.hpp" @@ -172,10 +173,10 @@ void ServerEnvironment::init(int argc, char* argv[], const std::string& path_to_ if (ecf_white_list_file_ == Str::WHITE_LIST_FILE()) ecf_white_list_file_ = host_name_.prefix_host_and_port(port, ecf_white_list_file_); - if (ecf_passwd_file_ == Str::ECF_PASSWD()) + if (ecf_passwd_file_ == ecf::environment::ECF_PASSWD) ecf_passwd_file_ = host_name_.prefix_host_and_port(port, ecf_passwd_file_); - if (ecf_passwd_custom_file_ == Str::ECF_CUSTOM_PASSWD()) + if (ecf_passwd_custom_file_ == ecf::environment::ECF_CUSTOM_PASSWD) ecf_passwd_custom_file_ = host_name_.prefix_host_and_port(port, ecf_passwd_custom_file_); // Change directory to ECF_HOME and check thats its accessible @@ -369,10 +370,10 @@ void ServerEnvironment::variables(std::vectorpath()); theRetVec.emplace_back(std::string("ECF_CHECK"), ecf_checkpt_file_); theRetVec.emplace_back(std::string("ECF_CHECKOLD"), ecf_backup_checkpt_file_); @@ -606,10 +607,10 @@ void ServerEnvironment::read_config_file(std::string& log_file_name, const std:: po::value(&ecf_white_list_file_)->default_value(Str::WHITE_LIST_FILE()), "Path name to file the list valid users and their access rights")( "ECF_PASSWD", - po::value(&ecf_passwd_file_)->default_value(Str::ECF_PASSWD()), + po::value(&ecf_passwd_file_)->default_value(ecf::environment::ECF_PASSWD), "Path name to passwd file")( "ECF_CUSTOM_PASSWD", - po::value(&ecf_passwd_custom_file_)->default_value(Str::ECF_CUSTOM_PASSWD()), + po::value(&ecf_passwd_custom_file_)->default_value(ecf::environment::ECF_CUSTOM_PASSWD), "Path name to custom passwd file, for user who don't use login name")( "ECF_TASK_THRESHOLD", po::value(&the_task_threshold)->default_value(JobProfiler::task_threshold_default()), @@ -650,9 +651,8 @@ void ServerEnvironment::read_environment_variables(std::string& log_file_name) { if (debug()) cout << "ServerEnvironment::read_environment_variables()\n"; - char* serverPort = getenv(Str::ECF_PORT().c_str()); - if (serverPort) { - std::string port = serverPort; + if (auto var = getenv(ecf::environment::ECF_PORT); var) { + std::string port = var; try { serverPort_ = ecf::convert_to(port); } @@ -663,9 +663,9 @@ void ServerEnvironment::read_environment_variables(std::string& log_file_name) { throw ServerEnvironmentException(ss.str()); } } - char* checkPtInterval = getenv("ECF_CHECKINTERVAL"); - if (checkPtInterval) { - std::string interval = checkPtInterval; + + if (auto var = getenv("ECF_CHECKINTERVAL"); var) { + std::string interval = var; try { checkPtInterval_ = ecf::convert_to(interval); } @@ -677,54 +677,37 @@ void ServerEnvironment::read_environment_variables(std::string& log_file_name) { } } - char* ecfHome = getenv(Str::ECF_HOME().c_str()); - if (ecfHome) - ecfHome_ = ecfHome; + ecf::environment::get_environment_variable(ecf::environment::ECF_HOME, ecfHome_); if (ecfHome_ == ".") { // expand to absolute paths ecfHome_ = fs::current_path().string(); } - char* logFileName = getenv("ECF_LOG"); - if (logFileName) - log_file_name = logFileName; + ecf::environment::get_environment_variable(ecf::environment::ECF_LOG, log_file_name); - char* checkPtFileName = getenv("ECF_CHECK"); - if (checkPtFileName) - ecf_checkpt_file_ = checkPtFileName; + ecf::environment::get_environment_variable("ECF_CHECK", ecf_checkpt_file_); - char* oldCheckPtFileName = getenv("ECF_CHECKOLD"); - if (oldCheckPtFileName) - ecf_backup_checkpt_file_ = oldCheckPtFileName; + ecf::environment::get_environment_variable("ECF_CHECKOLD", ecf_backup_checkpt_file_); - char* smsWhiteListFile = getenv("ECF_LISTS"); - if (smsWhiteListFile) - ecf_white_list_file_ = smsWhiteListFile; + ecf::environment::get_environment_variable("ECF_LISTS", ecf_white_list_file_); - char* passwd = getenv("ECF_PASSWD"); - if (passwd) - ecf_passwd_file_ = passwd; + ecf::environment::get_environment_variable(ecf::environment::ECF_PASSWD, ecf_passwd_file_); - char* custom_passwd = getenv("ECF_CUSTOM_PASSWD"); - if (custom_passwd) - ecf_passwd_custom_file_ = custom_passwd; + ecf::environment::get_environment_variable(ecf::environment::ECF_CUSTOM_PASSWD, ecf_passwd_custom_file_); - char* ecf_prune_node_log = getenv("ECF_PRUNE_NODE_LOG"); - if (ecf_prune_node_log) { + if (auto var = getenv("ECF_PRUNE_NODE_LOG"); var) { try { - ecf_prune_node_log_ = ecf::convert_to(ecf_prune_node_log); + ecf_prune_node_log_ = ecf::convert_to(var); } catch (const ecf::bad_conversion&) { std::stringstream ss; ss << "ServerEnviroment::read_environment_variables: ECF_PRUNE_NODE_LOG must be convertible to an integer, " "But found: " - << ecf_prune_node_log; + << var; throw ServerEnvironmentException(ss.str()); } } - if (getenv("ECF_DEBUG_SERVER")) { - debug_ = true; // can also be enabled via --debug option - } + ecf::environment::get_environment_variable("ECF_DEBUG_SERVER", debug_); #ifdef ECF_OPENSSL // IF ECF_SSL= 1 search server.crt @@ -732,15 +715,14 @@ void ServerEnvironment::read_environment_variables(std::string& log_file_name) { ssl_.enable_if_defined(serverHost_, the_port()); #endif - char* threshold = getenv("ECF_TASK_THRESHOLD"); - if (threshold) { - std::string task_threshold = threshold; + if (auto var = getenv("ECF_TASK_THRESHOLD"); var) { + std::string task_threshold = var; try { JobProfiler::set_task_threshold(ecf::convert_to(task_threshold)); } catch (...) { std::stringstream ss; - ss << "ServerEnvironment::read_environment_variables(): ECF_TASK_THRESHOLD is defined(" << threshold + ss << "ServerEnvironment::read_environment_variables(): ECF_TASK_THRESHOLD is defined(" << var << ") but value is *not* convertible to an integer\n"; throw ServerEnvironmentException(ss.str()); } @@ -807,7 +789,7 @@ std::string ServerEnvironment::dump() const { std::vector ServerEnvironment::expected_variables() { std::vector expected_variables; - expected_variables.push_back(Str::ECF_HOME()); + expected_variables.push_back(ecf::environment::ECF_HOME); expected_variables.emplace_back("ECF_LOG"); expected_variables.emplace_back("ECF_CHECK"); expected_variables.emplace_back("ECF_CHECKOLD"); @@ -822,8 +804,8 @@ std::vector ServerEnvironment::expected_variables() { expected_variables.emplace_back("ECF_PID"); expected_variables.emplace_back("ECF_VERSION"); expected_variables.emplace_back("ECF_LISTS"); - expected_variables.push_back(Str::ECF_PORT()); - expected_variables.push_back(Str::ECF_HOST()); + expected_variables.push_back(ecf::environment::ECF_PORT); + expected_variables.push_back(ecf::environment::ECF_HOST); expected_variables.emplace_back("ECF_INTERVAL"); expected_variables.emplace_back("ECF_PASSWD"); expected_variables.emplace_back("ECF_CUSTOM_PASSWD"); diff --git a/libs/server/test/TestServerEnvironment.cpp b/libs/server/test/TestServerEnvironment.cpp index c1c737560..1e6471c9e 100644 --- a/libs/server/test/TestServerEnvironment.cpp +++ b/libs/server/test/TestServerEnvironment.cpp @@ -17,6 +17,7 @@ #include "ecflow/core/CheckPt.hpp" #include "ecflow/core/Converter.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Host.hpp" #include "ecflow/core/Log.hpp" @@ -120,7 +121,7 @@ BOOST_AUTO_TEST_CASE(test_server_environment_log_file) { bool found_var = false; typedef std::pair mpair; for (const mpair& p : server_vars) { - if (Str::ECF_LOG() == p.first) { + if (ecf::environment::ECF_LOG == p.first) { BOOST_CHECK_MESSAGE(p.second == Log::instance()->path(), "Expected " << Log::instance()->path() << " but found " << p.second); found_var = true; @@ -189,7 +190,7 @@ BOOST_AUTO_TEST_CASE(test_server_config_file) { typedef std::pair mpair; for (const mpair& p : server_vars) { // std::cout << "server variables " << p.first << " " << p.second << "\n"; - if (Str::ECF_HOME() == p.first) { + if (ecf::environment::ECF_HOME == p.first) { BOOST_CHECK_MESSAGE(p.second == fs::current_path().string(), "for ECF_HOME expected " << fs::current_path().string() << " but found " << p.second); continue; @@ -266,7 +267,7 @@ BOOST_AUTO_TEST_CASE(test_server_config_file) { std::string port = Str::DEFAULT_PORT_NUMBER(); if (getenv("ECF_PORT")) port = getenv("ECF_PORT"); - std::string expected = host.prefix_host_and_port(port, Str::ECF_PASSWD()); + std::string expected = host.prefix_host_and_port(port, ecf::environment::ECF_PASSWD); BOOST_CHECK_MESSAGE(p.second == expected, "for ECF_PASSWD expected " << expected << " but found " << p.second); diff --git a/libs/simulator/test/TestAutoArchive.cpp b/libs/simulator/test/TestAutoArchive.cpp index 040c14102..df06db9d6 100644 --- a/libs/simulator/test/TestAutoArchive.cpp +++ b/libs/simulator/test/TestAutoArchive.cpp @@ -15,6 +15,7 @@ #include "TestUtil.hpp" #include "ecflow/attribute/AutoArchiveAttr.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -40,8 +41,8 @@ BOOST_AUTO_TEST_CASE(test_autoarchive_suite) { // ****: Since we have no time dependencies the simulator calendar increment // ****: is in hours. Hence autoarchive at hour resolution Defs theDefs; - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), - File::test_data("libs/simulator/test", "libs/simulator")); // required for archive + theDefs.set_server().add_or_update_user_variables( + ecf::environment::ECF_HOME, File::test_data("libs/simulator/test", "libs/simulator")); // required for archive suite_ptr s1, s2, s3; { ClockAttr clockAttr(true); @@ -125,8 +126,8 @@ BOOST_AUTO_TEST_CASE(test_autoarchive_ast_node_reset) { // ****: Since we have no time dependencies the simulator calendar increment // ****: is in hours. Hence autoarchive at hour resolution Defs theDefs; - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), - File::test_data("libs/simulator/test", "libs/simulator")); // required for archive + theDefs.set_server().add_or_update_user_variables( + ecf::environment::ECF_HOME, File::test_data("libs/simulator/test", "libs/simulator")); // required for archive suite_ptr suite_s2; suite_ptr suite_s3; @@ -200,8 +201,8 @@ BOOST_AUTO_TEST_CASE(test_autoarchive_ast_node_reset) { BOOST_AUTO_TEST_CASE(test_autoarchive_family) { cout << "Simulator:: ...test_autoarchive_family\n"; Defs theDefs; - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), - File::test_data("libs/simulator/test", "libs/simulator")); // required for archive + theDefs.set_server().add_or_update_user_variables( + ecf::environment::ECF_HOME, File::test_data("libs/simulator/test", "libs/simulator")); // required for archive { ClockAttr clockAttr(true); @@ -270,8 +271,8 @@ BOOST_AUTO_TEST_CASE(test_autoarchive_family) { BOOST_AUTO_TEST_CASE(test_two_autoarchive_in_hierarchy) { cout << "Simulator:: ...test_two_autoarchive_in_hierarchy\n"; Defs theDefs; - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), - File::test_data("libs/simulator/test", "libs/simulator")); // required for archive + theDefs.set_server().add_or_update_user_variables( + ecf::environment::ECF_HOME, File::test_data("libs/simulator/test", "libs/simulator")); // required for archive suite_ptr suite; { diff --git a/libs/simulator/test/TestAutoRestore.cpp b/libs/simulator/test/TestAutoRestore.cpp index 90442a013..6ba3313bf 100644 --- a/libs/simulator/test/TestAutoRestore.cpp +++ b/libs/simulator/test/TestAutoRestore.cpp @@ -15,6 +15,7 @@ #include "TestUtil.hpp" #include "ecflow/attribute/AutoArchiveAttr.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/AutoRestoreAttr.hpp" @@ -41,8 +42,8 @@ BOOST_AUTO_TEST_CASE(test_autorestore_suite) { // ****: Since we have no time dependencies the simulator calendar increment // ****: is in hours. Hence autoarchive at hour resolution Defs theDefs; - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), - File::test_data("libs/simulator/test", "libs/simulator")); // required for archive + theDefs.set_server().add_or_update_user_variables( + ecf::environment::ECF_HOME, File::test_data("libs/simulator/test", "libs/simulator")); // required for archive string s1_path; { ClockAttr clockAttr(true); @@ -96,8 +97,8 @@ BOOST_AUTO_TEST_CASE(test_autorestore_family) { // before // *** autorestore Defs theDefs; - theDefs.set_server().add_or_update_user_variables(Str::ECF_HOME(), - File::test_data("libs/simulator/test", "libs/simulator")); // required for archive + theDefs.set_server().add_or_update_user_variables( + ecf::environment::ECF_HOME, File::test_data("libs/simulator/test", "libs/simulator")); // required for archive std::vector vec; { diff --git a/libs/test/TestClkSync.cpp b/libs/test/TestClkSync.cpp index 221e20e3d..6fc935cbd 100644 --- a/libs/test/TestClkSync.cpp +++ b/libs/test/TestClkSync.cpp @@ -19,6 +19,7 @@ #include "TestFixture.hpp" #include "ecflow/attribute/VerifyAttr.hpp" #include "ecflow/core/DurationTimer.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/PrintStyle.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Family.hpp" @@ -85,7 +86,7 @@ BOOST_AUTO_TEST_CASE(test_suite_calendar_sync) { TestClean clean_at_start_and_end; // When using ECF_SSL sync is to slow. - if (getenv("ECF_SSL")) { + if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { cout << " ignore test undel ECF_SSL\n"; return; } @@ -139,8 +140,8 @@ BOOST_AUTO_TEST_CASE(test_suite_calendar_sync) { boost::posix_time::ptime sync_clock_suiteTime = TestFixture::client().defs()->suiteVec()[0]->calendar().suiteTime(); ss << " Sync clock suite time:" << to_simple_string(sync_clock_suiteTime) << " full_sync(" - << TestFixture::client().server_reply().full_sync() << ")" - << " in_sync(" << TestFixture::client().server_reply().in_sync() << ") cal_count(" + << TestFixture::client().server_reply().full_sync() << ")" << " in_sync(" + << TestFixture::client().server_reply().in_sync() << ") cal_count(" << TestFixture::client().defs()->updateCalendarCount() << ")\n"; // suiteVec is now invalidated @@ -149,8 +150,8 @@ BOOST_AUTO_TEST_CASE(test_suite_calendar_sync) { boost::posix_time::ptime sync_full_suiteTime = TestFixture::client().defs()->suiteVec()[0]->calendar().suiteTime(); ss << " Sync full suite time :" << to_simple_string(sync_full_suiteTime) << " full_sync(" - << TestFixture::client().server_reply().full_sync() << ")" - << " in_sync(" << TestFixture::client().server_reply().in_sync() << ") cal_count(" + << TestFixture::client().server_reply().full_sync() << ")" << " in_sync(" + << TestFixture::client().server_reply().in_sync() << ") cal_count(" << TestFixture::client().defs()->updateCalendarCount() << ")\n"; BOOST_REQUIRE_MESSAGE(sync_clock_suiteTime == sync_full_suiteTime, diff --git a/libs/test/src/ServerTestHarness.cpp b/libs/test/src/ServerTestHarness.cpp index 5d273a552..ff053a837 100644 --- a/libs/test/src/ServerTestHarness.cpp +++ b/libs/test/src/ServerTestHarness.cpp @@ -21,6 +21,7 @@ #include "ecflow/core/Converter.hpp" #include "ecflow/core/DurationTimer.hpp" #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/File.hpp" #include "ecflow/core/Str.hpp" #include "ecflow/node/Defs.hpp" @@ -95,9 +96,9 @@ defs_ptr ServerTestHarness::doRun(Defs& theClientDefs, for (suite_ptr s : theClientDefs.suiteVec()) { // Always override these to correctly locate files. - s->addVariable(Variable(Str::ECF_HOME(), ecf_home)); + s->addVariable(Variable(ecf::environment::ECF_HOME, ecf_home)); s->addVariable(Variable("ECF_CLIENT_EXE_PATH", theClientExePath)); - s->addVariable(Variable(Str::ECF_INCLUDE(), TestFixture::includes())); + s->addVariable(Variable(ecf::environment::ECF_INCLUDE, TestFixture::includes())); if (s->findVariable("SLEEPTIME").empty()) s->addVariable(Variable("SLEEPTIME", "1")); diff --git a/libs/udp/src/ecflow/udp/UDPServerEnvironment.cpp b/libs/udp/src/ecflow/udp/UDPServerEnvironment.cpp index 044c6f257..b02839097 100644 --- a/libs/udp/src/ecflow/udp/UDPServerEnvironment.cpp +++ b/libs/udp/src/ecflow/udp/UDPServerEnvironment.cpp @@ -10,7 +10,7 @@ #include "ecflow/udp/UDPServerEnvironment.hpp" -#include +#include "ecflow/core/Environment.hpp" namespace ecf { @@ -32,9 +32,7 @@ const std::unordered_map options_map = {{UDPServerEnvi UDPServerEnvironment::UDPServerEnvironment() : environment_{} { for (auto variable : variables) { - if (const char* value = ::getenv(variable); value) { - environment_[variable] = value; - } + ecf::environment::get_environment_variable(variable, environment_[variable]); } }