Environment Variable Utilities#

Revision History#

Version

Date

Author

Purpose

1

September 2026

Nino Tarantino

Initial version


Introduction#

The Environment Variable Utilities model provides C++ interfaces to retrieve environment variables with a variety of selectable fallback behaviors if the requested variable is not set.


Requirements#

  • CML-ENV-UTILS-1: The model shall provide an option to terminate the program if a requested environment variable is not set.

  • CML-ENV-UTILS-2: The model shall provide an option to return a default value if a requested environment variable is not set.

  • CML-ENV-UTILS-3: The model shall provide an option to throw an error if a requested environment variable is not set.

  • CML-ENV-UTILS-4: The model shall provide a method for expanding environment variables in a user-defined string.


Model Specifications#

Architectural Considerations#

Existing External Capabilities#

The C++ standard library has the std::getenv function, which exposes a C-based API. This model wraps that standard library function with a C++ API and performs error handling and environment variable expansion.

Model Structure#

Functions

inline std::string getenv_or_exit(const std::string &var_name, const std::function<void(int)> &exit_fn = std::exit)#

Retrieve the environment variable if it is set, otherwise terminate the program

Parameters:
  • var_name -- Environment variable to retrieve

  • exit_fn -- Function to be called if the variable is not set

Returns:

The contents of the environment variable

inline std::string getenv_or_default(const std::string &var_name, const std::string &default_value)#

Retrieve the environment variable if it is set, otherwise return a user-defined default value

Parameters:
  • var_name -- Environment variable to retrieve

  • default_value -- Value to return if the variable is not set

Returns:

The contents of the environment variable if set, otherwise the default value

inline std::string getenv_or_throw(const std::string &var_name) noexcept(false)#

Retrieve the environment variable if it is set, otherwise throw an error

Throws:

std::runtime_error -- If the environment variable is not set

Parameters:

var_name -- Environment variable to retrieve

Returns:

The contents of the environment variable

std::string expand_env_variables(const std::string &input) noexcept(false)#

Expand all environment variables in a given string

Recognizes both ${VAR} and $VAR forms. For the braced form, the name is whatever appears between the braces. For the bare form, the name runs until the next delimiter (space, '/', etc.) or the end of the string. Environment variables are assumed to begin with a letter and contain only letters, numbers, and underscores.

If the string has neither of the aforementioned forms, it is considered to not contain any environment variables. In this case, calling this function returns exactly what was passed to it.

Note

Nested environment variables are not supported. Variables of the form ${SOME${VAR}} will not expand correctly.

Throws:

std::runtime_error -- If any expanded environment variable is not set

Parameters:

input -- String containing environment variables

Returns:

The original string with environment variables expanded

Mathematical Formulation#

No mathematical formulation.


User's Guide#

Retrieving an Environment Variable#

Exit if the Variable is Not Set#

Retrieve an environment variable's value, or else call std::exit(EXIT_FAILURE) if the requested value is not set:

const std::string var = getenv_or_exit("MY_ENV_VAR");

Alternatively, a user-defined exit function may be provided. This function will be called with EXIT_FAILURE as its argument.

auto my_exit_function = [](int return_value) -> void {
    // Some user-defined logic goes here.
};
const std::string var = getenv_or_exit("MY_ENV_VAR", my_exit_function);

Use a Default Value if the Variable is Not Set#

Define a default value to use if the requested environment variable is not set:

const std::string var = getenv_or_default("MY_ENV_VAR", "fallback-value");

Throw an Error if the Variable is Not Set#

Retrieve an environment variable's value, or else throw a runtime error:

try {
    const std::string var = getenv_or_throw("MY_ENV_VAR");
} catch (const std::runtime_error& err) {
    // Handle the missing variable.
}

Expanding Environment Variables in a String#

Expand all environment variables in a string:

const std::filesystem::path data_path = expand_env_variables("${DATA_DIR}/${SCENARIO_NAME}/data.csv");

Note that an std::runtime_error is always thrown if any environment variable in the provided string is not set.

Extension#

As the model is simply a collection of functions, users may augment it with their own environment variable handling functions.


Verification#

Each model requirement has associated unit tests which verify it. The unit tests are described in the Unit-Test Cases section.

Code Coverage#

------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines     Exec  Cover   Missing
------------------------------------------------------------------------------
include/env_utils.hh
                                              17       17   100%
src/env_utils.cc
                                              20       20   100%
------------------------------------------------------------------------------
TOTAL                                         37       37   100%
------------------------------------------------------------------------------

See detailed coverage information here.

Exceptions#

N/A

Unit-Test Cases#

Each requirement is verified by one or more unit tests constructed using the GoogleTest framework.

Requirements Traceability#

Requirement

Test(s) Which Verify It

CML-ENV-UTILS-1

EnvUtils.Exit

CML-ENV-UTILS-2

EnvUtils.DefaultValue

CML-ENV-UTILS-3

EnvUtils.Throw

CML-ENV-UTILS-4

EnvUtils.ExpandBracedEnvironmentVariables EnvUtils.ExpandUnBracedEnvironmentVariables EnvUtils.ExpandEnvironmentVariablesEdgeCases

EnvUtils.Exit#

Purpose: Demonstrate that the correct environment variable data is returned if the variable exists, or else calls an exit-handling function.

Requirement: Satisfactory conclusion of the test satisfies the verification of requirement CML-ENV-UTILS-1.

Procedure:

  1. Set the contents of an environment variable, CML_ENVUTILS_TEST_VAR_EXIT_TEST, equal to "test-value".

  2. Query the contents of CML_ENVUTILS_TEST_VAR_EXIT_TEST using the getenv_or_exit() function.

  3. Clear the contents of an environment variable, DOES_NOT_EXIST_EXIT_TEST.

  4. Query the contents of DOES_NOT_EXIST_EXIT_TEST using the getenv_or_exit() function.

Success Criteria: The contents retrieved from the CML_ENVUTILS_TEST_VAR_EXIT_TEST environment variable should match what they were set to in the first step of the test. Attempting to query the contents of the DOES_NOT_EXIST_EXIT_TEST environment variable should result in an exit-handling function being called.

Results:

Test Step

Expectation

Result

getenv_or_exit() called with CML_ENVUTILS_TEST_VAR_EXIT_TEST

"test-value" returned

Pass

getenv_or_exit() called with DOES_NOT_EXIST_EXIT_TEST

Exit handler called

Pass

By showing that:

  • Attempting to retrieve the value of an environment variable previously set in the test returns that same value

  • Attempting to retrieve the value of an environment variable which was previously un-set in the test results in an exit-handler function being called

the test EnvUtils.Exit verifies that the model satisfies the requirement CML-ENV-UTILS-1.

EnvUtils.DefaultValue#

Purpose: Demonstrate that the correct environment variable data is returned if the variable exists, or else returns a user-defined default value.

Requirement: Satisfactory conclusion of the test satisfies the verification of requirement CML-ENV-UTILS-2.

Procedure:

  1. Set the contents of an environment variable, CML_ENVUTILS_TEST_VAR_DEFAULT_VALUE_TEST, equal to "test-value".

  2. Query the contents of CML_ENVUTILS_TEST_VAR_DEFAULT_VALUE_TEST using the getenv_or_default() function with a default value of "DEFAULT"

  3. Clear the contents of an environment variable, DOES_NOT_EXIST_DEFAULT_VALUE_TEST.

  4. Query the contents of DOES_NOT_EXIST_DEFAULT_VALUE_TEST using the getenv_or_default() function with a default value of "DEFAULT"

Success Criteria: The contents retrieved from the CML_ENVUTILS_TEST_VAR_DEFAULT_VALUE_TEST environment variable should match what they were set to in the first step of the test. Attempting to query the contents of the DOES_NOT_EXIST_DEFAULT_VALUE_TEST environment variable should result in the default value of "DEFAULT" being returned instead.

Results:

Test Step

Expectation

Result

getenv_or_default() called with CML_ENVUTILS_TEST_VAR_DEFAULT_VALUE_TEST

"test-value" returned

Pass

getenv_or_default() called with DOES_NOT_EXIST_DEFAULT_VALUE_TEST

"DEFAULT" returned

Pass

By showing that:

  • Attempting to retrieve the value of an environment variable previously set in the test returns that same value

  • Attempting to retrieve the value of an environment variable which was previously un-set in the test results in a specified default value being returned instead

the test EnvUtils.DefaultValue verifies that the model satisfies the requirement CML-ENV-UTILS-2.

EnvUtils.Throw#

Purpose: Demonstrate that the correct environment variable data is returned if the variable exists, or else throws an error.

Requirement: Satisfactory conclusion of the test satisfies the verification of requirement CML-ENV-UTILS-3.

Procedure:

  1. Set the contents of an environment variable, CML_ENVUTILS_TEST_VAR_THROW_TEST, equal to "test-value".

  2. Query the contents of CML_ENVUTILS_TEST_VAR_THROW_TEST using the getenv_or_throw() function.

  3. Clear the contents of an environment variable, DOES_NOT_EXIST_THROW_TEST.

  4. Query the contents of DOES_NOT_EXIST_THROW_TEST using the getenv_or_throw() function.

Success Criteria: The contents retrieved from the CML_ENVUTILS_TEST_VAR_THROW_TEST environment variable should match what they were set to in the first step of the test. Attempting to query the contents of the DOES_NOT_EXIST_THROW_TEST environment variable should result in an error being thrown.

Results:

Test Step

Expectation

Result

getenv_or_throw() called with CML_ENVUTILS_TEST_VAR_THROW_TEST

"test-value" returned

Pass

getenv_or_throw() called with DOES_NOT_EXIST_THROW_TEST

std::runtime_error thrown

Pass

By showing that:

  • Attempting to retrieve the value of an environment variable previously set in the test returns that same value

  • Attempting to retrieve the value of an environment variable which was previously un-set in the test results in an error being throw

the test EnvUtils.Throw verifies that the model satisfies the requirement CML-ENV-UTILS-3.

EnvUtils.ExpandBracedEnvironmentVariables#

Purpose: Demonstrate that environment variables are correctly expanded when specified in braced form.

Requirement: Satisfactory conclusion of the test partially satisfies the verification of requirement CML-ENV-UTILS-4.

Procedure:

  1. Set the contents of an environment variable, CML_ENVUTILS_TEST_VAR_BRACED1, equal to "blue".

  2. Set the contents of an environment variable, CML_ENVUTILS_TEST_VAR_BRACED2, equal to "mouse".

  3. Expand the environment variables in the string "I have a pet ${CML_ENVUTILS_TEST_VAR_BRACED1} ${CML_ENVUTILS_TEST_VAR_BRACED2}".

  4. Attempt to expand the string when one of the environment variables is not set.

  5. Attempt to expand the string when all of the environment variables are not set.

Success Criteria: When both environment variables are defined, the string should expand to "I have a pet blue mouse". If any of the variables are not set, an error is thrown.

Results:

Test Step

Expectation

Result

expand_env_variables() called with both variables set

"I have a pet blue mouse" returned

Pass

expand_env_variables() called with one variable not set

std::runtime_error thrown

Pass

expand_env_variables() called with neither variable set

std::runtime_error thrown

Pass

By showing that:

  • Both environment variables are expanded correctly when set

  • An error is thrown if any environment variable in the string is not set

the test EnvUtils.ExpandBracedEnvironmentVariables partially verifies that the model satisfies the requirement CML-ENV-UTILS-4.

EnvUtils.ExpandUnbracedEnvironmentVariables#

This test is identical to to braced environment variable expansion test, except it uses the $UNBRACED_VAR form instead of the ${BRACED_VAR_FORM}. The test procedure, inputs, and expected outputs are otherwise identical.

the test EnvUtils.ExpandUnbracedEnvironmentVariables partially verifies that the model satisfies the requirement CML-ENV-UTILS-4.

EnvUtils.ExpandEnvironmentVariablesEdgeCases#

Purpose: Demonstrate that environment variables are correctly expanded under certain edge conditions.

Requirement: Satisfactory conclusion of the test partially satisfies the verification of requirement CML-ENV-UTILS-4.

Procedure:

  1. Attempt to expand environment variables in an input which has no environment variables to expand.

  2. Attempt to expand unbraced environment variables with so spaces between them.

Success Criteria:

  1. A string with no environment variables to expand is returned unmodified.

  2. Two unbraced environment variables which are not separated by a space are correctly expanded.

Test Step

Expectation

Result

expand_env_variables() called with "No environment variables"

"No environment variables" returned

Pass

expand_env_variables() called with two consecutive, unbraced variables

Variables are both expanded

Pass

By showing that:

  • A string with no environment variables to expand is returned unmodified

  • Two unbraced environment variables which are not separated by a space are correctly expanded

the test EnvUtils.ExpandEnvironmentVariablesEdgeCases partially verifies that the model satisfies the requirement CML-ENV-UTILS-4.