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}; // class EnvVarTestCase
114
116 : TestCase("environment-variable-cache")
117{
118}
119
121{
122 UnsetVariable("destructor");
123}
124
125void
126EnvVarTestCase::SetVariable(const std::string& where, const std::string& value)
127{
129 bool ok = EnvironmentVariable::Set(m_variable, value);
130 NS_TEST_EXPECT_MSG_EQ(ok, true, where << ": failed to set variable");
131
132 // Double check
133 const char* envCstr = std::getenv(m_variable.c_str());
134 NS_TEST_EXPECT_MSG_NE(envCstr, nullptr, where << ": failed to retrieve variable just set");
135 NS_TEST_EXPECT_MSG_EQ(envCstr, value, where << ": failed to retrieve value just set");
136}
137
138void
139EnvVarTestCase::UnsetVariable(const std::string& where)
140{
142 bool ok = EnvironmentVariable::Unset(where);
143 NS_TEST_EXPECT_MSG_EQ(ok, true, where << ": failed to unset variable");
144}
145
146void
147EnvVarTestCase::Check(const std::string& where, const std::string& envValue, KeyValueStore expect)
148{
150
151 // Print the expect and which ones were found in dict
152 std::cout << "\n"
153 << where << " variable: '" << envValue << "', expect[" << expect.size() << "]"
154 << ", dict[" << dict.size() << "]\n";
155
156 NS_TEST_EXPECT_MSG_EQ(dict.size(), expect.size(), where << ": unequal dictionary sizes");
157
158 std::size_t i{0};
159 for (const auto& kv : expect)
160 {
161 std::cout << " [" << i++ << "] '" << kv.first << "'\t'" << kv.second << "'";
162
163 auto loc = dict.find(kv.first);
164 bool found = loc != dict.end();
165 std::cout << (found ? "\tfound" : "\tNOT FOUND");
166 NS_TEST_EXPECT_MSG_EQ(found, true, where << ": expected key not found: " << kv.second);
167
168 if (found)
169 {
170 bool match = kv.second == loc->second;
171 if (match)
172 {
173 std::cout << ", match";
174 }
175 else
176 {
177 std::cout << ", NO MATCH: '" << loc->second << "'";
178 }
179 NS_TEST_EXPECT_MSG_EQ(kv.second, loc->second, where << ": key found, value mismatch");
180 }
181 std::cout << "\n";
182 ++i;
183 }
184
185 // Now just check dict for unexpected values
186 i = 0;
187 bool first{true};
188 for (const auto& kv : dict)
189 {
190 bool found = expect.find(kv.first) != expect.end();
191 if (!found)
192 {
193 std::cout << (first ? "Unexpected keys:" : "");
194 first = false;
195 std::cout << " [" << i << "] '" << kv.first << "'\t'" << kv.second << "'"
196 << " unexpected key, value\n";
197 }
198 ++i;
199 }
200}
201
202void
203EnvVarTestCase::SetAndCheck(const std::string& where,
204 const std::string& envValue,
205 KeyValueStore expect)
206{
207 SetVariable(where, envValue);
208 Check(where, envValue, expect);
209}
210
211void
212EnvVarTestCase::CheckGet(const std::string& where, const std::string& key, KeyFoundType expect)
213{
214 auto [found, value] = EnvironmentVariable::Get(m_variable, key, m_delimiter);
216 expect.first,
217 where << ": key '" << key << "' " << (expect.first ? "not " : "")
218 << "found unexpectedly");
220 expect.second,
221 where << ": incorrect value for key '" << key << "'");
222}
223
224void
225EnvVarTestCase::SetCheckAndGet(const std::string& where,
226 const std::string& envValue,
227 KeyValueStore expectDict,
228 const std::string& key,
229 KeyFoundType expectValue)
230{
231 SetAndCheck(where, envValue, expectDict);
232 CheckGet(where, key, expectValue);
233}
234
235void
237{
238 // Environment variable not set.
239 UnsetVariable("unset");
240 Check("unset", "", {});
241 auto [found, value] = EnvironmentVariable::Get(m_variable);
242 NS_TEST_EXPECT_MSG_EQ(found, false, "unset: variable found when not set");
243 NS_TEST_EXPECT_MSG_EQ(value.empty(), true, "unset: non-empty value from unset variable");
244
245 // Variable set but empty
246#ifndef __WIN32__
247 // Windows doesn't support environment variables with empty values
248 SetCheckAndGet("empty", "", {}, "", {true, ""});
249#endif
250
251 // Key not in variable
252 SetCheckAndGet("no-key",
253 "not|the|right=value",
254 {{"not", ""}, {"the", ""}, {"right", "value"}},
255 "key",
256 {false, ""});
257
258 // Key only (no delimiter): "key"
259 SetCheckAndGet("key-only", "key", {{"key", ""}}, "key", {true, ""});
260
261 // Extra delimiter: ":key", "key:"
262 SetCheckAndGet("front-|", "|key", {{"key", ""}}, "key", {true, ""});
263 SetCheckAndGet("back-|", "key|", {{"key", ""}}, "key", {true, ""});
264
265 // Double delimiter: "||key", "key||"
266 SetCheckAndGet("front-||", "||key", {{"key", ""}}, "key", {true, ""});
267 SetCheckAndGet("back-||", "key||", {{"key", ""}}, "key", {true, ""});
268
269 // Two keys: "key1|key2"
270 SetCheckAndGet("two keys", "key1|key2", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
271 CheckGet("two keys", "key2", {true, ""});
272
273 // Extra/double delimiters| "||key1|key2", "|key1|key2", "key1||key2", "key1|key2|",
274 // "key1|key2||"
275 SetCheckAndGet("||two keys", "||key1|key2", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
276 CheckGet("||two keys", "key2", {true, ""});
277 SetCheckAndGet("two keys||", "key1|key2||", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
278 CheckGet("two keys||", "key2", {true, ""});
279
280 // Key=value: "key=value"
281 SetCheckAndGet("key-val", "key=value", {{"key", "value"}}, "key", {true, "value"});
282
283 // Mixed key-only, key=value| "key1|key2=|key3|key4=value"
284 SetCheckAndGet("mixed",
285 "key1|key2=value|key3|key4=value",
286 {{"key1", ""}, {"key2", "value"}, {"key3", ""}, {"key4", "value"}},
287 "key1",
288 {true, ""});
289 CheckGet("mixed", "key2", {true, "value"});
290 CheckGet("mixed", "key3", {true, ""});
291 CheckGet("mixed", "key4", {true, "value"});
292
293 // Empty/missing value| "key="
294 SetCheckAndGet("key=", "key=", {{"key", ""}}, "key", {true, ""});
295
296 // Extra `=`| "key==value"
297 SetCheckAndGet("key==", "key==", {{"key", "="}}, "key", {true, "="});
298
299 // Finish last line of verbose output
300 std::cout << std::endl;
301}
302
303/**
304 * \ingroup environ-var-tests
305 *
306 * Environment variable handling test suite.
307 */
309{
310 public:
312};
313
319
320/**
321 * \ingroup environ-var-tests
322 * Static variable for test initialization.
323 */
325
326} // namespace tests
327
328} // 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.