A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
environment-variable-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Lawrence Livermore National Laboratory
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
7 */
8
9#include "ns3/environment-variable.h"
10#include "ns3/test.h"
11
12#include <cstdlib> // getenv
13
14namespace ns3
15{
16
17namespace tests
18{
19
20/**
21 * @file
22 * @ingroup environ-var-tests
23 * Environment variable caching test suite
24 */
25
26/**
27 * @ingroup core-tests
28 * @defgroup environ-var-tests Environment variable caching tests
29 */
30
31/**
32 * @ingroup environ-var-tests
33 *
34 * EnvironmentVariable tests
35 */
37{
38 public:
39 /** Constructor */
41
42 /** Destructor */
43 ~EnvVarTestCase() override;
44
45 private:
46 /** Run the tests */
47 void DoRun() override;
48
49 /** The key,value store */
51
52 /** The return type from EnvironmentVariable::Get() */
54
55 /**
56 * Set the test environment variable.
57 * @param where The test condition being checked.
58 * @param value The value to set.
59 */
60 void SetVariable(const std::string& where, const std::string& value);
61
62 /**
63 * Unset the test environment variable.
64 * @param where The test condition being checked.
65 */
66 void UnsetVariable(const std::string& where);
67
68 /**
69 * Read \p envValue and check that it contains only the key,value pairs
70 * from \p expect.
71 * @param where The test condition being checked.
72 * @param envValue The environment variable to parse and check.
73 * @param expect The set of key,values expected.
74 */
75 void Check(const std::string& where, const std::string& envValue, KeyValueStore expect);
76
77 /**
78 * Set and Check the variable.
79 * @param where The test condition being checked.
80 * @param envValue The environment variable to parse and check.
81 * @param expect The set of key,values expected.
82 */
83 void SetAndCheck(const std::string& where, const std::string& envValue, KeyValueStore expect);
84
85 /**
86 * Check the result from a Get.
87 * @param where The test condition being checked.
88 * @param key The key to check.
89 * @param expect The expected result.
90 */
91 void CheckGet(const std::string& where, const std::string& key, KeyFoundType expect);
92
93 /**
94 * Set, Check, and Get a variable.
95 * @param where The test condition being checked.
96 * @param envValue The environment variable to parse and check.
97 * @param expectDict The set of key,values expected.
98 * @param key The key to check.
99 * @param expectValue The expected result.
100 */
101 void SetCheckAndGet(const std::string& where,
102 const std::string& envValue,
103 KeyValueStore expectDict,
104 const std::string& key,
105 KeyFoundType expectValue);
106
107 /** Always use a non-default delimiter. */
108 const std::string m_delimiter{"|"};
109
110 /** Test environment variable name. */
111 const std::string m_variable{"NS_ENVVAR_TEST"};
112
113 // end of class EnvVarTestCase
114};
115
117 : TestCase("environment-variable-cache")
118{
119}
120
122{
123 UnsetVariable("destructor");
124}
125
126void
127EnvVarTestCase::SetVariable(const std::string& where, const std::string& value)
128{
130 bool ok = EnvironmentVariable::Set(m_variable, value);
131 NS_TEST_EXPECT_MSG_EQ(ok, true, where << ": failed to set variable");
132
133 // Double check
134 const char* envCstr = std::getenv(m_variable.c_str());
135 NS_TEST_EXPECT_MSG_NE(envCstr, nullptr, where << ": failed to retrieve variable just set");
136 NS_TEST_EXPECT_MSG_EQ(envCstr, value, where << ": failed to retrieve value just set");
137}
138
139void
140EnvVarTestCase::UnsetVariable(const std::string& where)
141{
143 bool ok = EnvironmentVariable::Unset(where);
144 NS_TEST_EXPECT_MSG_EQ(ok, true, where << ": failed to unset variable");
145}
146
147void
148EnvVarTestCase::Check(const std::string& where, const std::string& envValue, KeyValueStore expect)
149{
151
152 // Print the expect and which ones were found in dict
153 std::cout << "\n"
154 << where << " variable: '" << envValue << "', expect[" << expect.size() << "]"
155 << ", dict[" << dict.size() << "]\n";
156
157 NS_TEST_EXPECT_MSG_EQ(dict.size(), expect.size(), where << ": unequal dictionary sizes");
158
159 std::size_t i{0};
160 for (const auto& kv : expect)
161 {
162 std::cout << " [" << i++ << "] '" << kv.first << "'\t'" << kv.second << "'";
163
164 auto loc = dict.find(kv.first);
165 bool found = loc != dict.end();
166 std::cout << (found ? "\tfound" : "\tNOT FOUND");
167 NS_TEST_EXPECT_MSG_EQ(found, true, where << ": expected key not found: " << kv.second);
168
169 if (found)
170 {
171 bool match = kv.second == loc->second;
172 if (match)
173 {
174 std::cout << ", match";
175 }
176 else
177 {
178 std::cout << ", NO MATCH: '" << loc->second << "'";
179 }
180 NS_TEST_EXPECT_MSG_EQ(kv.second, loc->second, where << ": key found, value mismatch");
181 }
182 std::cout << "\n";
183 ++i;
184 }
185
186 // Now just check dict for unexpected values
187 i = 0;
188 bool first{true};
189 for (const auto& kv : dict)
190 {
191 bool found = expect.find(kv.first) != expect.end();
192 if (!found)
193 {
194 std::cout << (first ? "Unexpected keys:" : "");
195 first = false;
196 std::cout << " [" << i << "] '" << kv.first << "'\t'" << kv.second << "'"
197 << " unexpected key, value\n";
198 }
199 ++i;
200 }
201}
202
203void
204EnvVarTestCase::SetAndCheck(const std::string& where,
205 const std::string& envValue,
206 KeyValueStore expect)
207{
208 SetVariable(where, envValue);
209 Check(where, envValue, expect);
210}
211
212void
213EnvVarTestCase::CheckGet(const std::string& where, const std::string& key, KeyFoundType expect)
214{
215 auto [found, value] = EnvironmentVariable::Get(m_variable, key, m_delimiter);
217 expect.first,
218 where << ": key '" << key << "' " << (expect.first ? "not " : "")
219 << "found unexpectedly");
221 expect.second,
222 where << ": incorrect value for key '" << key << "'");
223}
224
225void
226EnvVarTestCase::SetCheckAndGet(const std::string& where,
227 const std::string& envValue,
228 KeyValueStore expectDict,
229 const std::string& key,
230 KeyFoundType expectValue)
231{
232 SetAndCheck(where, envValue, expectDict);
233 CheckGet(where, key, expectValue);
234}
235
236void
238{
239 // Environment variable not set.
240 UnsetVariable("unset");
241 Check("unset", "", {});
242 auto [found, value] = EnvironmentVariable::Get(m_variable);
243 NS_TEST_EXPECT_MSG_EQ(found, false, "unset: variable found when not set");
244 NS_TEST_EXPECT_MSG_EQ(value.empty(), true, "unset: non-empty value from unset variable");
245
246 // Variable set but empty
247#ifndef __WIN32__
248 // Windows doesn't support environment variables with empty values
249 SetCheckAndGet("empty", "", {}, "", {true, ""});
250#endif
251
252 // Key not in variable
253 SetCheckAndGet("no-key",
254 "not|the|right=value",
255 {{"not", ""}, {"the", ""}, {"right", "value"}},
256 "key",
257 {false, ""});
258
259 // Key only (no delimiter): "key"
260 SetCheckAndGet("key-only", "key", {{"key", ""}}, "key", {true, ""});
261
262 // Extra delimiter: ":key", "key:"
263 SetCheckAndGet("front-|", "|key", {{"key", ""}}, "key", {true, ""});
264 SetCheckAndGet("back-|", "key|", {{"key", ""}}, "key", {true, ""});
265
266 // Double delimiter: "||key", "key||"
267 SetCheckAndGet("front-||", "||key", {{"key", ""}}, "key", {true, ""});
268 SetCheckAndGet("back-||", "key||", {{"key", ""}}, "key", {true, ""});
269
270 // Two keys: "key1|key2"
271 SetCheckAndGet("two keys", "key1|key2", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
272 CheckGet("two keys", "key2", {true, ""});
273
274 // Extra/double delimiters| "||key1|key2", "|key1|key2", "key1||key2", "key1|key2|",
275 // "key1|key2||"
276 SetCheckAndGet("||two keys", "||key1|key2", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
277 CheckGet("||two keys", "key2", {true, ""});
278 SetCheckAndGet("two keys||", "key1|key2||", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
279 CheckGet("two keys||", "key2", {true, ""});
280
281 // Key=value: "key=value"
282 SetCheckAndGet("key-val", "key=value", {{"key", "value"}}, "key", {true, "value"});
283
284 // Mixed key-only, key=value| "key1|key2=|key3|key4=value"
285 SetCheckAndGet("mixed",
286 "key1|key2=value|key3|key4=value",
287 {{"key1", ""}, {"key2", "value"}, {"key3", ""}, {"key4", "value"}},
288 "key1",
289 {true, ""});
290 CheckGet("mixed", "key2", {true, "value"});
291 CheckGet("mixed", "key3", {true, ""});
292 CheckGet("mixed", "key4", {true, "value"});
293
294 // Empty/missing value| "key="
295 SetCheckAndGet("key=", "key=", {{"key", ""}}, "key", {true, ""});
296
297 // Extra `=`| "key==value"
298 SetCheckAndGet("key==", "key==", {{"key", "="}}, "key", {true, "="});
299
300 // Finish last line of verbose output
301 std::cout << std::endl;
302}
303
304/**
305 * @ingroup environ-var-tests
306 *
307 * Environment variable handling test suite.
308 */
310{
311 public:
313};
314
320
321/**
322 * @ingroup environ-var-tests
323 * Static variable for test initialization.
324 */
326
327} // namespace tests
328
329} // namespace ns3
std::unordered_map< std::string, std::string > KeyValueStore
Key, value store type.
static KeyFoundType Get(const std::string &envvar, const std::string &key="", const std::string &delim=";")
Get the value corresponding to a key from an environment variable.
static bool Unset(const std::string &variable)
Unset an environment variable.
std::pair< bool, std::string > KeyFoundType
Result of a key lookup.
static void Clear()
Clear the instance, forcing all new lookups.
static bool Set(const std::string &variable, const std::string &value)
Set an environment variable.
static std::shared_ptr< Dictionary > GetDictionary(const std::string &envvar, const std::string &delim=";")
Get the dictionary for a particular environment variable.
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
void SetVariable(const std::string &where, const std::string &value)
Set the test environment variable.
void CheckGet(const std::string &where, const std::string &key, KeyFoundType expect)
Check the result from a Get.
const std::string m_delimiter
Always use a non-default delimiter.
const std::string m_variable
Test environment variable name.
void Check(const std::string &where, const std::string &envValue, KeyValueStore expect)
Read envValue and check that it contains only the key,value pairs from expect.
void SetAndCheck(const std::string &where, const std::string &envValue, KeyValueStore expect)
Set and Check the variable.
EnvironmentVariable::Dictionary::KeyValueStore KeyValueStore
The key,value store.
EnvironmentVariable::KeyFoundType KeyFoundType
The return type from EnvironmentVariable::Get()
void UnsetVariable(const std::string &where)
Unset the test environment variable.
void SetCheckAndGet(const std::string &where, const std::string &envValue, KeyValueStore expectDict, const std::string &key, KeyFoundType expectValue)
Set, Check, and Get a variable.
Environment variable handling test suite.
static EnvironmentVariableTestSuite g_EnvironmentVariableTestSuite
Static variable for test initialization.
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
Definition test.h:656
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:241
Definition first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.