diff --git a/libs/base/src/ecflow/base/Openssl.cpp b/libs/base/src/ecflow/base/Openssl.cpp index 97bd009be..67d9c9cb6 100644 --- a/libs/base/src/ecflow/base/Openssl.cpp +++ b/libs/base/src/ecflow/base/Openssl.cpp @@ -80,8 +80,8 @@ void Openssl::enable(std::string host, const std::string& port) { } void Openssl::enable_if_defined(std::string host, const std::string& port) { - if (auto ecf_ssl = getenv(ecf::environment::ECF_SSL); ecf_ssl) { - std::string ecf_ssl_env = ecf_ssl; + if (auto ecf_ssl = ecf::environment::fetch(ecf::environment::ECF_SSL); ecf_ssl) { + std::string ecf_ssl_env = ecf_ssl.value(); if (host == Str::LOCALHOST()) host = Host().name(); @@ -160,10 +160,7 @@ std::string Openssl::get_password() const { } std::string Openssl::certificates_dir() const { - std::string home_path; - ecf::environment::get_environment_variable("HOME", home_path); - home_path += "/.ecflowrc/ssl/"; - return home_path; + return ecf::environment::get("HOME") + "/.ecflowrc/ssl/"; } std::string Openssl::pem() const { diff --git a/libs/client/src/ecflow/client/ClientEnvironment.cpp b/libs/client/src/ecflow/client/ClientEnvironment.cpp index 6d9a0b4e0..6fb705ed2 100644 --- a/libs/client/src/ecflow/client/ClientEnvironment.cpp +++ b/libs/client/src/ecflow/client/ClientEnvironment.cpp @@ -224,13 +224,13 @@ std::string ClientEnvironment::toString() const { std::string ClientEnvironment::hostSpecified() { std::string specified_host; - ecf::environment::get_environment_variable(ecf::environment::ECF_HOST, specified_host); + ecf::environment::get(ecf::environment::ECF_HOST, specified_host); return specified_host; } std::string ClientEnvironment::portSpecified() { std::string specified_port = Str::DEFAULT_PORT_NUMBER(); - ecf::environment::get_environment_variable(ecf::environment::ECF_PORT, specified_port); + ecf::environment::get(ecf::environment::ECF_PORT, specified_port); return specified_port; } @@ -239,37 +239,37 @@ void ClientEnvironment::read_environment_variables() { std::cout << "ClientEnvironment::read_environment_variables()\n"; #endif - ecf::environment::get_environment_variable(ecf::environment::ECF_NAME, task_path_); + ecf::environment::get(ecf::environment::ECF_NAME, task_path_); - ecf::environment::get_environment_variable(ecf::environment::ECF_PASS, jobs_password_); + ecf::environment::get(ecf::environment::ECF_PASS, jobs_password_); - ecf::environment::get_environment_variable(ecf::environment::ECF_TRYNO, task_try_num_); + ecf::environment::get(ecf::environment::ECF_TRYNO, task_try_num_); - ecf::environment::get_environment_variable("ECF_HOSTFILE", host_file_); + ecf::environment::get("ECF_HOSTFILE", host_file_); - ecf::environment::get_environment_variable(ecf::environment::ECF_RID, remote_id_); + ecf::environment::get(ecf::environment::ECF_RID, remote_id_); - ecf::environment::get_environment_variable("ECF_USER", user_name_); + ecf::environment::get("ECF_USER", user_name_); - ecf::environment::get_environment_variable("ECF_TIMEOUT", timeout_); + ecf::environment::get("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_); + ecf::environment::get("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("ECF_CONNECT_TIMEOUT", connect_timeout_); - ecf::environment::get_environment_variable("ECF_DENIED", denied_); + ecf::environment::get("ECF_DENIED", denied_); - ecf::environment::get_environment_variable("NO_ECF", no_ecf_); + ecf::environment::get("NO_ECF", no_ecf_); - ecf::environment::get_environment_variable("ECF_DEBUG_CLIENT", debug_); + ecf::environment::get("ECF_DEBUG_CLIENT", debug_); - if (auto var = getenv("ECF_DEBUG_LEVEL"); var) { + if (auto var = ecf::environment::fetch("ECF_DEBUG_LEVEL"); var) { try { - Ecf::set_debug_level(ecf::convert_to(var)); + Ecf::set_debug_level(ecf::convert_to(var.value())); } catch (...) { throw std::runtime_error("The environment variable ECF_DEBUG_LEVEL must be an unsigned integer."); @@ -284,8 +284,8 @@ void ClientEnvironment::read_environment_variables() { port = host_vec_[0].second; // first entry is the config port } - if (auto var = getenv(ecf::environment::ECF_PORT); var) { - port = var; + if (auto var = ecf::environment::fetch(ecf::environment::ECF_PORT); var) { + port = var.value(); host_vec_.clear(); // remove config settings, net effect is overriding host_vec_.emplace_back(host, port); } @@ -381,8 +381,8 @@ const std::string& ClientEnvironment::get_password(const char* env, const std::s return passwd_; } - if (auto file = getenv(env); file) { - std::string user_passwd_file = file; + if (auto file = ecf::environment::fetch(env); file) { + std::string user_passwd_file = file.value(); // cout << " ClientEnvironment::get_password() ECF_CUSTOM_PASSWD " << user_passwd_file << "\n"; if (!user_passwd_file.empty() && fs::exists(user_passwd_file)) { // cout << " ClientEnvironment::get_password() LOADING password file\n"; diff --git a/libs/client/test/InvokeServer.hpp b/libs/client/test/InvokeServer.hpp index 70440521d..da9ea9f9a 100644 --- a/libs/client/test/InvokeServer.hpp +++ b/libs/client/test/InvokeServer.hpp @@ -38,7 +38,7 @@ class InvokeServer { if (!msg.empty()) { std::cout << msg << " port(" << port_ << ")"; #ifdef ECF_OPENSSL - if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { + if (ecf::environment::has(ecf::environment::ECF_SSL)) { std::cout << " (ssl)"; } #endif diff --git a/libs/client/test/SCPort.cpp b/libs/client/test/SCPort.cpp index 668004daa..796d25c60 100644 --- a/libs/client/test/SCPort.cpp +++ b/libs/client/test/SCPort.cpp @@ -32,7 +32,7 @@ int SCPort::thePort_ = 3144; std::string SCPort::next() { bool debug = false; - ecf::environment::get_environment_variable("ECF_DEBUG_TEST", debug); + ecf::environment::get("ECF_DEBUG_TEST", debug); if (debug) { std::cout << "\nSCPort::next() : "; @@ -40,16 +40,15 @@ std::string SCPort::next() { // Allow parallel tests - if (auto ECF_FREE_PORT = getenv("ECF_FREE_PORT"); ECF_FREE_PORT) { + if (auto port = ecf::environment::fetch("ECF_FREE_PORT"); port) { if (debug) { - std::cout << " seed_port=ECF_FREE_PORT=(" << ECF_FREE_PORT << ")"; + std::cout << " seed_port=ECF_FREE_PORT=(" << port.value() << ")"; } - std::string port = ECF_FREE_PORT; try { - thePort_ = ecf::convert_to(port); + thePort_ = ecf::convert_to(port.value()); } catch (...) { - std::cout << "SCPort::next() ECF_FREE_PORT(" << ECF_FREE_PORT << ") not convertible to an integer\n"; + std::cout << "SCPort::next() ECF_FREE_PORT(" << port.value() << ") not convertible to an integer\n"; } } @@ -61,13 +60,12 @@ std::string SCPort::next() { } if (host == Str::LOCALHOST()) { - if (auto ecf_port = getenv(ecf::environment::ECF_PORT); ecf_port) { - std::string port = ecf_port; - if (!port.empty()) { + if (auto port = ecf::environment::fetch(ecf::environment::ECF_PORT); port) { + if (!port.value().empty()) { if (debug) { - std::cout << " ECF_PORT('" << ecf_port << "')\n"; + std::cout << " ECF_PORT('" << port.value() << "')\n"; } - return port; + return port.value(); } } if (debug) { diff --git a/libs/client/test/TestServer.cpp b/libs/client/test/TestServer.cpp index d65195265..424c1fec4 100644 --- a/libs/client/test/TestServer.cpp +++ b/libs/client/test/TestServer.cpp @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(test_server_stress_test) { ClientInvoker theClient(invokeServer.host(), invokeServer.port()); int load = 125; #ifdef ECF_OPENSSL - if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { + if (ecf::environment::has(ecf::environment::ECF_SSL)) { load = 30; } #endif @@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(test_server_group_stress_test) { int load = 125; #ifdef ECF_OPENSSL - if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { + if (ecf::environment::has(ecf::environment::ECF_SSL)) { load = 30; } #endif @@ -411,7 +411,7 @@ BOOST_AUTO_TEST_CASE(test_server_stress_test_2) { #endif #ifdef ECF_OPENSSL - if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { + if (ecf::environment::has(ecf::environment::ECF_SSL)) { load = 10; } #endif diff --git a/libs/client/test/TestSinglePerf.cpp b/libs/client/test/TestSinglePerf.cpp index 5ec3abea4..a37a94ce4 100644 --- a/libs/client/test/TestSinglePerf.cpp +++ b/libs/client/test/TestSinglePerf.cpp @@ -347,7 +347,7 @@ void time_load_and_downloads(ClientInvoker& theClient, } BOOST_AUTO_TEST_CASE(test_perf_for_large_defs) { - if (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { + if (ecf::environment::has(ecf::environment::ECF_SSL)) { load_threshold_ms = 8000; // 4500; begin_threshold_ms = 800; // 400; sync_full_threshold_s = 4.5; // 2.6; @@ -359,11 +359,11 @@ BOOST_AUTO_TEST_CASE(test_perf_for_large_defs) { client_cmds_threshold_s = 950; // 8.5; } - if (auto ecf_test_defs_dir = getenv("ECF_TEST_DEFS_DIR"); !ecf_test_defs_dir) { + if (auto ecf_test_defs_dir = ecf::environment::fetch("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)) { - std::cout << "Ignoring test! Test definitions directory " << ecf_test_defs_dir << " does not exist\n"; + else if (!fs::exists(ecf_test_defs_dir.value())) { + std::cout << "Ignoring test! Test definitions directory " << ecf_test_defs_dir.value() << " does not exist\n"; } else { /// This will remove checkpt and backup , to avoid server from loading it. (i.e from previous test) @@ -372,7 +372,7 @@ BOOST_AUTO_TEST_CASE(test_perf_for_large_defs) { "Server failed to start on " << invokeServer.host() << ":" << invokeServer.port()); ClientInvoker theClient(invokeServer.host(), invokeServer.port()); - time_load_and_downloads(theClient, invokeServer.host(), invokeServer.port(), ecf_test_defs_dir); + time_load_and_downloads(theClient, invokeServer.host(), invokeServer.port(), ecf_test_defs_dir.value()); } } diff --git a/libs/core/src/ecflow/core/EcfPortLock.hpp b/libs/core/src/ecflow/core/EcfPortLock.hpp index 1aadf806d..7a2f06ec7 100644 --- a/libs/core/src/ecflow/core/EcfPortLock.hpp +++ b/libs/core/src/ecflow/core/EcfPortLock.hpp @@ -67,7 +67,7 @@ class EcfPortLock { // We need the *SAME* location so that different process find the same file. // When going across compiler the root_build_dir is not sufficient std::string path = File::root_source_dir(); - ecf::environment::get_environment_variable("ECF_PORT_LOCK_DIR", path); + ecf::environment::get("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 index 23d5dc7c4..ff9116f48 100644 --- a/libs/core/src/ecflow/core/Environment.hpp +++ b/libs/core/src/ecflow/core/Environment.hpp @@ -11,6 +11,10 @@ #ifndef ecflow_core_Environment_HPP #define ecflow_core_Environment_HPP +#include + +#include "ecflow/core/Message.hpp" + namespace ecf { namespace environment { @@ -48,60 +52,81 @@ constexpr const char* ECF_USER = "ECF_USER"; namespace /* anonymous */ { template -struct Environment +struct Wrapper +{ + static std::optional get(const char* name) { + if (auto var = std::getenv(name); var) { + return T{var}; + } + return std::nullopt; + } +}; + +template <> +struct Wrapper { - static void get(const char* name, T& value) { + static std::optional get(const char* name) { if (auto var = std::getenv(name); var) { - value = T{var}; + return std::make_optional(var); } + return std::nullopt; } }; template <> -struct Environment +struct Wrapper { - static void get(const char* name, int& value) { + static std::optional get(const char* name) { if (auto var = std::getenv(name); var) { - value = atoi(var); + return atoi(var); } + return std::nullopt; } }; template <> -struct Environment +struct Wrapper { - static void get(const char* name, unsigned int& value) { + static std::optional get(const char* name) { if (auto var = std::getenv(name); var) { - value = atoi(var); + return atoi(var); } + return std::nullopt; } }; template <> -struct Environment +struct Wrapper { - static void get(const char* name, long& value) { + static std::optional get(const char* name) { if (auto var = std::getenv(name); var) { - value = atol(var); + return atol(var); } + return std::nullopt; } }; template <> -struct Environment +struct Wrapper { - static void get(const char* name, bool& value) { + static std::optional get(const char* name) { if (auto var = std::getenv(name); var) { - value = true; + return true; } + return std::nullopt; } }; } // namespace +struct EnvVarNotFound : public std::runtime_error +{ + explicit EnvVarNotFound(std::basic_string what) : std::runtime_error(what) {} +}; + /** * @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. + * If the environment variable is not found, 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. @@ -111,15 +136,57 @@ struct Environment * @param value */ template -void get_environment_variable(const char* name, T& value) { - Environment::get(name, value); +void get(const char* name, T& value) { + if (auto found = Wrapper::get(name); found) { + value = found.value(); + } +} + +/** + * @brief Retrieves the environment variable value and returns it. + * If the environment variable is not found, an exception is thrown. + * + * 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 result is true. + * + * @tparam T + * @param name + */ +template +T get(const char* name) { + if (auto found = Wrapper::get(name); found) { + return found.value(); + } + + throw EnvVarNotFound(Message(name).str()); } -inline bool has_environment_variable(const char* name) { +/** + * @brief Retrieves the environment variable value and returns it (wrapped in an std::optional<>). + * If the environment variable is not found, std::nullopt is returned. + * + * 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 result is true. + * + * @tparam T + * @param name + */ +template +std::optional fetch(const char* name) { + return Wrapper::get(name); +} + +/** + * @brief Checks if an environment variable is set. + * + * @tparam T + * @param name + */ +inline bool has(const char* name) { return std::getenv(name) != nullptr; } -}; // namespace environment +} // namespace environment } // namespace ecf diff --git a/libs/core/src/ecflow/core/File.cpp b/libs/core/src/ecflow/core/File.cpp index e3a6aac11..3147cf1c6 100644 --- a/libs/core/src/ecflow/core/File.cpp +++ b/libs/core/src/ecflow/core/File.cpp @@ -16,6 +16,7 @@ #include #include "ecflow/core/Ecf.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/core/Log.hpp" #include "ecflow/core/NodePath.hpp" #include "ecflow/core/Str.hpp" @@ -54,7 +55,7 @@ const std::string& File::ECF_EXTN() { /// Search for the file, in $PATH return the first path that matches or an empty file, if not std::string File::which(const std::string& file) { - std::string env_paths = getenv("PATH"); + std::string env_paths = ecf::environment::get("PATH"); if (!env_paths.empty()) { std::string path; std::vector paths; @@ -839,12 +840,12 @@ static std::string bjam_workspace_dir() { stem = current_path.stem().string(); count++; if (count == 100) { - char* workspace = getenv("WK"); - if (workspace == NULL) { + auto workspace = ecf::environment::fetch("WK"); + if (!workspace) { throw std::runtime_error("File::bjam_workspace_dir() failed to find ecflow in a directory name, up the " "directory tree and WK undefined"); } - std::string the_workspace_dir = workspace; + std::string the_workspace_dir = workspace.value(); return the_workspace_dir; } } @@ -983,9 +984,9 @@ std::string File::find_ecf_client_path() { std::string File::test_data(const std::string& rel_path, const std::string& dir) { std::string test_file; - char* work_space = getenv("WK"); // for ecbuild - if (work_space != nullptr) { - test_file = std::string(work_space); + + if (auto workspace = ecf::environment::fetch("WK"); workspace) { + test_file = workspace.value(); if (!rel_path.empty() && rel_path[0] != '/') test_file += "/"; test_file += rel_path; diff --git a/libs/core/test/TestFile.cpp b/libs/core/test/TestFile.cpp index 13418614d..73fc59b2b 100644 --- a/libs/core/test/TestFile.cpp +++ b/libs/core/test/TestFile.cpp @@ -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 (ecf::environment::has_environment_variable("ECFLOW_CRAY_BATCH")) { + if (ecf::environment::has("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 0de7b333c..441066915 100644 --- a/libs/core/test/TestSanitizerAS.cpp +++ b/libs/core/test/TestSanitizerAS.cpp @@ -34,7 +34,7 @@ int integer_returning_function() { #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"); + return ecf::environment::has("ECF_TEST_SANITIZER_AS"); } // *** This test does not seem work with address sanitiser **** diff --git a/libs/core/test/TestSanitizerUB.cpp b/libs/core/test/TestSanitizerUB.cpp index 9a8f7ae1b..3eddbb5bd 100644 --- a/libs/core/test/TestSanitizerUB.cpp +++ b/libs/core/test/TestSanitizerUB.cpp @@ -40,7 +40,7 @@ Derived* getDerived() { 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"); + return ecf::environment::has("ECF_TEST_SANITIZER_UB"); } BOOST_AUTO_TEST_CASE(test_sanitizer_invalid_object_size, diff --git a/libs/core/test/TestStringSplitPerf.cpp b/libs/core/test/TestStringSplitPerf.cpp index f086710c5..a23d110c6 100644 --- a/libs/core/test/TestStringSplitPerf.cpp +++ b/libs/core/test/TestStringSplitPerf.cpp @@ -252,14 +252,14 @@ BOOST_AUTO_TEST_CASE(test_str_split_perf_with_file) { // Time for std::string_view(2) 2001774 times = 0.752472 // Now test performance of splitting with a big DEFS file - char* ecf_test_defs_dir = getenv("ECF_TEST_DEFS_DIR"); + auto ecf_test_defs_dir = ecf::environment::fetch("ECF_TEST_DEFS_DIR"); if (!ecf_test_defs_dir) { - std::cout << "Ingoring test, since directory defined by environment variable(ECF_TEST_DEFS_DIR) is missing"; + std::cout << "Igoring tests, since directory defined by environment variable(ECF_TEST_DEFS_DIR) is missing"; return; } - std::string path = std::string(ecf_test_defs_dir) + "/vsms2.31415.def"; + std::string path = ecf_test_defs_dir.value() + "/vsms2.31415.def"; if (!fs::exists(path)) { - std::cout << "Ingoring test, since file defined by environment variable(ECF_TEST_DEFS_DIR) " << path + std::cout << "Igoring test, since file defined by environment variable(ECF_TEST_DEFS_DIR) " << path << " is missing"; return; } diff --git a/libs/node/src/ecflow/node/JobCreationCtrl.cpp b/libs/node/src/ecflow/node/JobCreationCtrl.cpp index bd87bd01b..2ffb5b446 100644 --- a/libs/node/src/ecflow/node/JobCreationCtrl.cpp +++ b/libs/node/src/ecflow/node/JobCreationCtrl.cpp @@ -10,17 +10,22 @@ #include "ecflow/node/JobCreationCtrl.hpp" -#include // for getenv() #include #include +#include "ecflow/core/Environment.hpp" + void JobCreationCtrl::generate_temp_dir() { - if (!getenv("TMPDIR")) + if (auto tmpdir = ecf::environment::fetch("TMPDIR"); tmpdir) { + tempDirForJobGeneration_ = tmpdir.value(); + tempDirForJobGeneration_ += "/ecf_check_job_creation"; + if (fs::exists(tempDirForJobGeneration_)) { + fs::remove_all(tempDirForJobGeneration_); + } + std::cout << "JobCreationCtrl::generate_temp_dir() " << tempDirForJobGeneration_ << "\n"; + } + else { throw std::runtime_error( "JobCreationCtrl::generate_temp_dir(), The environment variable TMPDIR is not defined"); - tempDirForJobGeneration_ = getenv("TMPDIR"); - tempDirForJobGeneration_ += "/ecf_check_job_creation"; - if (fs::exists(tempDirForJobGeneration_)) - fs::remove_all(tempDirForJobGeneration_); - std::cout << "JobCreationCtrl::generate_temp_dir() " << tempDirForJobGeneration_ << "\n"; + } } diff --git a/libs/node/test/TestEcfFile.cpp b/libs/node/test/TestEcfFile.cpp index 469884316..5e60c4094 100644 --- a/libs/node/test/TestEcfFile.cpp +++ b/libs/node/test/TestEcfFile.cpp @@ -8,7 +8,6 @@ * nor does it submit to any jurisdiction. */ -#include // for getenv #include #include @@ -31,7 +30,7 @@ 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"); + return ecf::environment::has("ECFLOW_CRAY_BATCH"); } BOOST_AUTO_TEST_SUITE(U_Node) @@ -73,7 +72,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 (auto var = getenv("ECFLOW_CRAY_BATCH"); var) { + if (ecf::environment::has("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -156,7 +155,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_include_file) { BOOST_AUTO_TEST_CASE(test_ECFLOW_495) { // This tests for a regression where, *NOT* all the include file were processed. cout << "ANode:: ...test_ECFLOW_495"; - if (getenv("ECFLOW_CRAY_BATCH")) { + if (ecf::environment::has("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -229,7 +228,7 @@ BOOST_AUTO_TEST_CASE(test_ECFLOW_495) { BOOST_AUTO_TEST_CASE(test_ECF_SCRIPT_CMD_ECFLOW_427) { cout << "ANode:: ...test_ECF_SCRIPT_CMD_ECFLOW_427"; - if (getenv("ECFLOW_CRAY_BATCH")) { + if (ecf::environment::has("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -376,7 +375,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_include_file) { cout << "ANode:: ...test_ecf_include_file"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -459,7 +458,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_include_multi_paths_ECFLOW_261) { cout << "ANode:: ...test_ecf_include_multi_paths_ECFLOW_261"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -542,7 +541,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_include_ECFLOW_274) { cout << "ANode:: ...test_ecf_include_ECFLOW_274"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -637,7 +636,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_used_variables) { cout << "ANode:: ...test_ecf_simple_used_variables"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -709,7 +708,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_used_variables_with_comments) { cout << "ANode:: ...test_ecf_simple_used_variables_with_comments"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -780,7 +779,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_simple_used_variables_errors) { cout << "ANode:: ...test_ecf_simple_used_variables_errors"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -842,7 +841,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file) { cout << "ANode:: ...test_ecf_file"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -1038,7 +1037,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_includenoop) { cout << "ANode:: ...test_ecf_file_includenopp"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -1132,7 +1131,7 @@ BOOST_AUTO_TEST_CASE(test_ecf_file_override_ECF_JOB) { cout << "ANode:: ...test_ecf_file_override_ECF_JOB"; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -1303,7 +1302,7 @@ BOOST_AUTO_TEST_CASE(test_manual_files) { BOOST_AUTO_TEST_CASE(test_ECFLOW_672) { // test for recursive includes that are not recursive cout << "ANode:: ...test_ECFLOW_672"; - if (getenv("ECFLOW_CRAY_BATCH")) { + if (ecf::environment::has("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } @@ -1359,7 +1358,7 @@ static void basic_test_template(const std::string& test_name, bool expect_success = true) { cout << "ANode:: ..." << test_name; // 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("ECFLOW_CRAY_BATCH")) { cout << " **** SKIPPING test, until HPC team can fix File::createMissingDirectories.(like mkdir -p) *****\n"; return; } diff --git a/libs/rest/src/ecflow/http/Client.cpp b/libs/rest/src/ecflow/http/Client.cpp index aa9697d9f..73fb592e9 100644 --- a/libs/rest/src/ecflow/http/Client.cpp +++ b/libs/rest/src/ecflow/http/Client.cpp @@ -27,17 +27,17 @@ namespace ecf::http { -const char* const ECF_USER = getenv(ecf::environment::ECF_USER); -const char* const ECF_PASS = getenv(ecf::environment::ECF_PASS); +const auto ECF_USER = ecf::environment::fetch(ecf::environment::ECF_USER); +const auto ECF_PASS = ecf::environment::fetch(ecf::environment::ECF_PASS); bool authenticate(const httplib::Request& request, ClientInvoker* ci) { #ifdef ECF_OPENSSL auto auth_with_token = [&](const std::string& token) { if (TokenStorage::instance().verify(token)) { - if (ECF_USER != nullptr && ECF_PASS != nullptr) { - ci->set_user_name(std::string(ECF_USER)); - ci->set_password(std::string(ECF_PASS)); + if (ECF_USER && ECF_PASS) { + ci->set_user_name(ECF_USER.value()); + ci->set_password(ECF_PASS.value()); } return true; } diff --git a/libs/rest/src/ecflow/http/HttpServer.cpp b/libs/rest/src/ecflow/http/HttpServer.cpp index c528f8c58..98d3c9db6 100644 --- a/libs/rest/src/ecflow/http/HttpServer.cpp +++ b/libs/rest/src/ecflow/http/HttpServer.cpp @@ -26,16 +26,16 @@ HttpServer::HttpServer(int argc, char** argv) { } void read_environment() { - 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); + ecf::environment::get("ECF_RESTAPI_VERBOSE", opts.verbose); + ecf::environment::get("ECF_RESTAPI_NOSSL", opts.no_ssl); + ecf::environment::get("ECF_RESTAPI_POLLING_INTERVAL", opts.polling_interval); + ecf::environment::get("ECF_RESTAPI_PORT", opts.port); + ecf::environment::get("ECF_HOST", opts.ecflow_host); + ecf::environment::get("ECF_PORT", opts.ecflow_port); + ecf::environment::get("ECF_RESTAPI_TOKENS_FILE", opts.tokens_file); + ecf::environment::get("ECF_RESTAPI_CERT_DIRECTORY", opts.cert_directory); + ecf::environment::get("ECF_RESTAPI_MAX_UPDATE_INTERVAL", opts.max_polling_interval); + ecf::environment::get("ECF_HOST_PROTOCOL", opts.host_protocol); } void HttpServer::parse_args(int argc, char** argv) const { diff --git a/libs/rest/test/InvokeServer.hpp b/libs/rest/test/InvokeServer.hpp index fd16ad48c..572c6ff3b 100644 --- a/libs/rest/test/InvokeServer.hpp +++ b/libs/rest/test/InvokeServer.hpp @@ -29,7 +29,7 @@ class InvokeServer { public: InvokeServer() { std::string port; - ecf::environment::get_environment_variable(ecf::environment::ECF_PORT, port); + ecf::environment::get(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)); @@ -61,7 +61,7 @@ class InvokeServer { ~InvokeServer() { std::string port; - ecf::environment::get_environment_variable(ecf::environment::ECF_PORT, port); + ecf::environment::get(ecf::environment::ECF_PORT, port); BOOST_TEST_MESSAGE("*****InvokeServer:: Closing server on port " << port); { diff --git a/libs/rest/test/TestApiV1.cpp b/libs/rest/test/TestApiV1.cpp index 8d06e0eb1..a624ef48e 100644 --- a/libs/rest/test/TestApiV1.cpp +++ b/libs/rest/test/TestApiV1.cpp @@ -35,9 +35,9 @@ const std::string API_HOST("localhost"); const std::string API_KEY("3a8c3f7ac204d9c6370b5916bd8b86166c208e10776285edcbc741d56b5b4c1e"); std::unique_ptr create_certificate() { - const char* cert_dir = getenv("ECF_API_CERT_DIRECTORY"); - const std::string path_to_cert = - (cert_dir == nullptr) ? std::string(getenv("HOME")) + "/.ecflowrc/ssl/" : std::string(cert_dir); + auto cert_dir = ecf::environment::fetch("ECF_API_CERT_DIRECTORY"); + + const std::string path_to_cert = (cert_dir) ? cert_dir.value() : ecf::environment::get("HOME") + "/.ecflowrc/ssl/"; std::unique_ptr cert; @@ -66,9 +66,10 @@ std::unique_ptr create_token_file() { } void start_api_server() { + if (ecf::environment::has("NO_API_SERVER")) { + return; // terminate early, for debugging purposes + } - if (getenv("NO_API_SERVER") != nullptr) - return; // for debugging std::thread t([] { int argc = 3; char* argv[] = {(char*)"ecflow_http", (char*)"--polling_interval", (char*)"1", NULL}; @@ -82,13 +83,16 @@ void start_api_server() { } std::unique_ptr start_ecflow_server() { - if (getenv("NO_ECFLOW_SERVER") != nullptr) + if (ecf::environment::has("NO_ECFLOW_SERVER")) { return nullptr; + } auto srv = std::make_unique(); - BOOST_REQUIRE_MESSAGE(srv->server_started, "Server failed to start on port " << getenv("ECF_PORT")); - BOOST_TEST_MESSAGE("ecflow server at localhost:" << getenv("ECF_PORT")); + auto port = ecf::environment::get("ECF_PORT"); + BOOST_REQUIRE_MESSAGE(srv->server_started, "Server failed to start on port " << port); + BOOST_TEST_MESSAGE("ecflow server at localhost:" << port); + return srv; } diff --git a/libs/server/src/ecflow/server/ServerEnvironment.cpp b/libs/server/src/ecflow/server/ServerEnvironment.cpp index a7454da9f..1ccbdfef0 100644 --- a/libs/server/src/ecflow/server/ServerEnvironment.cpp +++ b/libs/server/src/ecflow/server/ServerEnvironment.cpp @@ -10,7 +10,6 @@ #include "ecflow/server/ServerEnvironment.hpp" -#include // for getenv() #include #include @@ -651,8 +650,8 @@ void ServerEnvironment::read_environment_variables(std::string& log_file_name) { if (debug()) cout << "ServerEnvironment::read_environment_variables()\n"; - if (auto var = getenv(ecf::environment::ECF_PORT); var) { - std::string port = var; + if (auto var = ecf::environment::fetch(ecf::environment::ECF_PORT); var) { + std::string port = var.value(); try { serverPort_ = ecf::convert_to(port); } @@ -664,8 +663,8 @@ void ServerEnvironment::read_environment_variables(std::string& log_file_name) { } } - if (auto var = getenv("ECF_CHECKINTERVAL"); var) { - std::string interval = var; + if (auto var = ecf::environment::fetch("ECF_CHECKINTERVAL"); var) { + std::string interval = var.value(); try { checkPtInterval_ = ecf::convert_to(interval); } @@ -677,37 +676,37 @@ void ServerEnvironment::read_environment_variables(std::string& log_file_name) { } } - ecf::environment::get_environment_variable(ecf::environment::ECF_HOME, ecfHome_); + ecf::environment::get(ecf::environment::ECF_HOME, ecfHome_); if (ecfHome_ == ".") { // expand to absolute paths ecfHome_ = fs::current_path().string(); } - ecf::environment::get_environment_variable(ecf::environment::ECF_LOG, log_file_name); + ecf::environment::get(ecf::environment::ECF_LOG, log_file_name); - ecf::environment::get_environment_variable("ECF_CHECK", ecf_checkpt_file_); + ecf::environment::get("ECF_CHECK", ecf_checkpt_file_); - ecf::environment::get_environment_variable("ECF_CHECKOLD", ecf_backup_checkpt_file_); + ecf::environment::get("ECF_CHECKOLD", ecf_backup_checkpt_file_); - ecf::environment::get_environment_variable("ECF_LISTS", ecf_white_list_file_); + ecf::environment::get("ECF_LISTS", ecf_white_list_file_); - ecf::environment::get_environment_variable(ecf::environment::ECF_PASSWD, ecf_passwd_file_); + ecf::environment::get(ecf::environment::ECF_PASSWD, ecf_passwd_file_); - ecf::environment::get_environment_variable(ecf::environment::ECF_CUSTOM_PASSWD, ecf_passwd_custom_file_); + ecf::environment::get(ecf::environment::ECF_CUSTOM_PASSWD, ecf_passwd_custom_file_); - if (auto var = getenv("ECF_PRUNE_NODE_LOG"); var) { + if (auto var = ecf::environment::fetch("ECF_PRUNE_NODE_LOG"); var) { try { - ecf_prune_node_log_ = ecf::convert_to(var); + ecf_prune_node_log_ = ecf::convert_to(var.value()); } 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: " - << var; + << var.value(); throw ServerEnvironmentException(ss.str()); } } - ecf::environment::get_environment_variable("ECF_DEBUG_SERVER", debug_); + ecf::environment::get("ECF_DEBUG_SERVER", debug_); #ifdef ECF_OPENSSL // IF ECF_SSL= 1 search server.crt @@ -715,14 +714,14 @@ void ServerEnvironment::read_environment_variables(std::string& log_file_name) { ssl_.enable_if_defined(serverHost_, the_port()); #endif - if (auto var = getenv("ECF_TASK_THRESHOLD"); var) { - std::string task_threshold = var; + if (auto var = ecf::environment::fetch("ECF_TASK_THRESHOLD"); var) { + std::string task_threshold = var.value(); try { JobProfiler::set_task_threshold(ecf::convert_to(task_threshold)); } catch (...) { std::stringstream ss; - ss << "ServerEnvironment::read_environment_variables(): ECF_TASK_THRESHOLD is defined(" << var + ss << "ServerEnvironment::read_environment_variables(): ECF_TASK_THRESHOLD is defined(" << var.value() << ") but value is *not* convertible to an integer\n"; throw ServerEnvironmentException(ss.str()); } @@ -810,8 +809,9 @@ std::vector ServerEnvironment::expected_variables() { expected_variables.emplace_back("ECF_PASSWD"); expected_variables.emplace_back("ECF_CUSTOM_PASSWD"); #ifdef ECF_OPENSSL - if (getenv("ECF_SSL")) + if (ecf::environment::has("ECF_SSL")) { expected_variables.emplace_back("ECF_SSL"); + } #endif return expected_variables; } diff --git a/libs/server/test/TestServer.cpp b/libs/server/test/TestServer.cpp index 21d57ffe2..89307f635 100644 --- a/libs/server/test/TestServer.cpp +++ b/libs/server/test/TestServer.cpp @@ -155,9 +155,9 @@ BOOST_AUTO_TEST_CASE(test_server) { // Hence the lock file is not always sufficient. // ECF_FREE_PORT should be unique among gnu,clang,intel, etc std::string the_port1 = "3144"; - char* test_ecf_port = getenv("ECF_FREE_PORT"); // from metabuilder, allow parallel tests - if (test_ecf_port) - the_port1 = test_ecf_port; + if (auto port = ecf::environment::fetch("ECF_FREE_PORT"); port) { // from metabuilder, allow parallel tests + the_port1 = port.value(); + } cout << " Find free port to start server, starting with port " << the_port1 << "\n"; auto the_port = ecf::convert_to(the_port1); diff --git a/libs/server/test/TestServerEnvironment.cpp b/libs/server/test/TestServerEnvironment.cpp index 1e6471c9e..87bf3369d 100644 --- a/libs/server/test/TestServerEnvironment.cpp +++ b/libs/server/test/TestServerEnvironment.cpp @@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(test_server_config_file) { "for ECF_HOME expected " << fs::current_path().string() << " but found " << p.second); continue; } - if (string("ECF_PORT") == p.first && !getenv("ECF_PORT")) { + if (string("ECF_PORT") == p.first && !ecf::environment::has("ECF_PORT")) { BOOST_CHECK_MESSAGE(p.second == Str::DEFAULT_PORT_NUMBER(), "for ECF_PORT expected " << Str::DEFAULT_PORT_NUMBER() << " but found " << p.second); continue; @@ -265,8 +265,9 @@ BOOST_AUTO_TEST_CASE(test_server_config_file) { Host host; std::string port = Str::DEFAULT_PORT_NUMBER(); - if (getenv("ECF_PORT")) - port = getenv("ECF_PORT"); + if (ecf::environment::has("ECF_PORT")) { + port = ecf::environment::has("ECF_PORT"); + } std::string expected = host.prefix_host_and_port(port, ecf::environment::ECF_PASSWD); BOOST_CHECK_MESSAGE(p.second == expected, diff --git a/libs/test/TestClkSync.cpp b/libs/test/TestClkSync.cpp index 6fc935cbd..623e9f7a5 100644 --- a/libs/test/TestClkSync.cpp +++ b/libs/test/TestClkSync.cpp @@ -86,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 (ecf::environment::has_environment_variable(ecf::environment::ECF_SSL)) { + if (ecf::environment::has(ecf::environment::ECF_SSL)) { cout << " ignore test undel ECF_SSL\n"; return; } diff --git a/libs/test/TestEvents.cpp b/libs/test/TestEvents.cpp index 845efd8ec..23228f4d8 100644 --- a/libs/test/TestEvents.cpp +++ b/libs/test/TestEvents.cpp @@ -18,6 +18,7 @@ #include "TestFixture.hpp" #include "ecflow/attribute/VerifyAttr.hpp" #include "ecflow/core/DurationTimer.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Family.hpp" #include "ecflow/node/Limit.hpp" @@ -150,7 +151,7 @@ BOOST_AUTO_TEST_CASE(test_event_and_query) { << TestFixture::client().get_string()); // Added since in 5.2.0 (only 5.2.0 server supports this behaviour) - if (!getenv("ECF_DISABLE_TEST_FOR_OLD_SERVERS")) { + if (!ecf::environment::has("ECF_DISABLE_TEST_FOR_OLD_SERVERS")) { BOOST_CHECK_MESSAGE(TestFixture::client().query("limit", suite->absNodePath(), "limit_x") == 0, "query command failed " << TestFixture::client().errorMsg()); BOOST_CHECK_MESSAGE(TestFixture::client().get_string() == "0", diff --git a/libs/test/TestInitAddVariable.cpp b/libs/test/TestInitAddVariable.cpp index da5a285ef..5315697ca 100644 --- a/libs/test/TestInitAddVariable.cpp +++ b/libs/test/TestInitAddVariable.cpp @@ -19,6 +19,7 @@ #include "ecflow/attribute/VerifyAttr.hpp" #include "ecflow/core/Converter.hpp" #include "ecflow/core/DurationTimer.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Family.hpp" #include "ecflow/node/Suite.hpp" @@ -36,7 +37,7 @@ BOOST_AUTO_TEST_SUITE(T_InitAddVariable) // This test does not have any time dependencies in the def file. BOOST_AUTO_TEST_CASE(test_init_add_variable) { // Added since in 5.2.0 (only 5.2.0 server supports this behaviour) - if (getenv("ECF_DISABLE_TEST_FOR_OLD_SERVERS")) { + if (ecf::environment::has("ECF_DISABLE_TEST_FOR_OLD_SERVERS")) { std::cout << "\n Disable test_init_add_variable for old server , re-enable when 5.2.0 is minimum version\n"; return; } diff --git a/libs/test/TestZombies.cpp b/libs/test/TestZombies.cpp index 71eb4d991..3ae0076b9 100644 --- a/libs/test/TestZombies.cpp +++ b/libs/test/TestZombies.cpp @@ -21,6 +21,7 @@ #include "ecflow/core/Child.hpp" #include "ecflow/core/Converter.hpp" #include "ecflow/core/DurationTimer.hpp" +#include "ecflow/core/Environment.hpp" #include "ecflow/node/Defs.hpp" #include "ecflow/node/Family.hpp" #include "ecflow/node/Suite.hpp" @@ -641,7 +642,7 @@ static void create_and_start_test(const std::string& suite_name, BOOST_AUTO_TEST_CASE(enable_debug_for_ECF_TRY_NO_Greater_than_one) { BOOST_CHECK_MESSAGE(true, "dummy test"); - if (getenv("ECF_DEBUG_ZOMBIES")) { + if (ecf::environment::has("ECF_DEBUG_ZOMBIES")) { ecf_debug_enabled = true; cout << "Test:: ... debug_enabled" << endl; } diff --git a/libs/test/src/TestFixture.cpp b/libs/test/src/TestFixture.cpp index 5d2f132eb..5b78173c8 100644 --- a/libs/test/src/TestFixture.cpp +++ b/libs/test/src/TestFixture.cpp @@ -10,7 +10,6 @@ #include "TestFixture.hpp" -#include // for getenv() #include // for ofstream #include @@ -99,8 +98,9 @@ void TestFixture::init(const std::string& project_test_dir) { host_ = ClientEnvironment::hostSpecified(); port_ = ClientEnvironment::portSpecified(); // returns ECF_PORT, otherwise Str::DEFAULT_PORT_NUMBER #ifdef ECF_OPENSSL - if (getenv("ECF_SSL")) + if (ecf::environment::has("ECF_SSL")) { std::cout << " Openssl enabled\n"; + } #endif if (!host_.empty() && host_ != Str::LOCALHOST()) { @@ -110,9 +110,9 @@ void TestFixture::init(const std::string& project_test_dir) { // Must use a file system accessible from the server. Use $SCRATCH // Duplicate test data, required to scratch area and reset ECF_HOME - char* scratchEnv = getenv("SCRATCH"); - assert(scratchEnv != NULL); - std::string theSCRATCHArea(scratchEnv); + auto scratchEnv = ecf::environment::fetch("SCRATCH"); + assert(scratchEnv); + std::string theSCRATCHArea(scratchEnv.value()); assert(!theSCRATCHArea.empty()); theSCRATCHArea += "/test_dir"; @@ -314,19 +314,20 @@ std::string TestFixture::theClientExePath() { if (serverOnLocalMachine()) return File::find_ecf_client_path(); - char* client_path_p = getenv("ECF_CLIENT_EXE_PATH"); - if (client_path_p == nullptr) { - + if (auto client_path_p = ecf::environment::fetch("ECF_CLIENT_EXE_PATH"); client_path_p) { + return client_path_p.value(); + } + else { // Try this before complaining std::string path = "/usr/local/apps/ecflow/current/bin/ecflow_client"; - if (fs::exists(path)) + if (fs::exists(path)) { return path; + } cout << "Please set ECF_CLIENT_EXE_PATH. This needs to be set to path to the client executable\n"; cout << "The client must be the one that was built on the same platform as the server\n"; assert(false); } - return string(client_path_p); } void TestFixture::clearLog() { @@ -341,14 +342,15 @@ std::string TestFixture::pathToLogFile() { return host.ecf_log_file(port_); } - char* pathToRemoteLog_p = getenv("ECF_LOG"); - if (pathToRemoteLog_p == nullptr) { + if (auto var = ecf::environment::fetch("ECF_LOG"); var) { + return var.value(); + } + else { cout << "TestFixture::pathToLogFile(): assert failed\n"; cout << "Please set ECF_LOG. This needs to be set to path to the log file\n"; cout << "that can be seen by the client and server\n"; assert(false); } - return std::string(pathToRemoteLog_p); } std::string TestFixture::local_ecf_home() { @@ -379,8 +381,8 @@ std::string TestFixture::local_ecf_home() { std::string rel_path = "data/ECF_HOME_" + build_type + "_" + compiler; // Allow post-fix to be added, to allow test to run in parallel - if (const char* custom_postfix = getenv("TEST_ECF_HOME_POSTFIX"); custom_postfix) { - rel_path += custom_postfix; + if (auto custom_postfix = ecf::environment::fetch("TEST_ECF_HOME_POSTFIX"); custom_postfix) { + rel_path += custom_postfix.value(); } std::string absolute_path = File::test_data_in_current_dir(rel_path); diff --git a/libs/test/src/ZombieUtill.cpp b/libs/test/src/ZombieUtill.cpp index 8373151fc..8b6f1b118 100644 --- a/libs/test/src/ZombieUtill.cpp +++ b/libs/test/src/ZombieUtill.cpp @@ -16,6 +16,7 @@ #include "ZombieUtil.hpp" #include "ecflow/attribute/Zombie.hpp" #include "ecflow/core/AssertTimer.hpp" +#include "ecflow/core/Environment.hpp" using namespace std; using namespace ecf; @@ -53,7 +54,7 @@ int ZombieUtil::do_zombie_user_action(User::Action uc, bool fail_if_to_long) { /// return the number of zombies set to user action; bool ecf_debug_zombies = false; - if (getenv("ECF_DEBUG_ZOMBIES")) { + if (ecf::environment::has("ECF_DEBUG_ZOMBIES")) { ecf_debug_zombies = true; cout << "\n do_zombie_user_action " << User::to_string(uc) << " expected_action_cnt " << expected_action_cnt << "\n"; diff --git a/libs/udp/src/ecflow/udp/UDPServerEnvironment.cpp b/libs/udp/src/ecflow/udp/UDPServerEnvironment.cpp index b02839097..406ccc3dd 100644 --- a/libs/udp/src/ecflow/udp/UDPServerEnvironment.cpp +++ b/libs/udp/src/ecflow/udp/UDPServerEnvironment.cpp @@ -32,7 +32,7 @@ const std::unordered_map options_map = {{UDPServerEnvi UDPServerEnvironment::UDPServerEnvironment() : environment_{} { for (auto variable : variables) { - ecf::environment::get_environment_variable(variable, environment_[variable]); + ecf::environment::get(variable, environment_[variable]); } }