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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
18 */
19
20#include "ns3/environment-variable.h"
21#include "ns3/test.h"
22
23#include <cstdlib> // getenv
24
25namespace ns3
26{
27
28namespace tests
29{
30
48{
49 public:
52
54 ~EnvVarTestCase() override;
55
56 private:
58 void DoRun() override;
59
62
65
71 void SetVariable(const std::string& where, const std::string& value);
72
77 void UnsetVariable(const std::string& where);
78
86 void Check(const std::string& where, const std::string& envValue, KeyValueStore expect);
87
94 void SetAndCheck(const std::string& where, const std::string& envValue, KeyValueStore expect);
95
102 void CheckGet(const std::string& where, const std::string& key, KeyFoundType expect);
103
112 void SetCheckAndGet(const std::string& where,
113 const std::string& envValue,
114 KeyValueStore expectDict,
115 const std::string& key,
116 KeyFoundType expectValue);
117
119 const std::string m_delimiter{"|"};
120
122 const std::string m_variable{"NS_ENVVAR_TEST"};
123
124}; // class EnvVarTestCase
125
127 : TestCase("environment-variable-cache")
128{
129}
130
132{
133 UnsetVariable("destructor");
134}
135
136void
137EnvVarTestCase::SetVariable(const std::string& where, const std::string& value)
138{
140 bool ok = EnvironmentVariable::Set(m_variable, value);
141 NS_TEST_EXPECT_MSG_EQ(ok, true, where << ": failed to set variable");
142
143 // Double check
144 const char* envCstr = std::getenv(m_variable.c_str());
145 NS_TEST_EXPECT_MSG_NE(envCstr, nullptr, where << ": failed to retrieve variable just set");
146 NS_TEST_EXPECT_MSG_EQ(envCstr, value, where << ": failed to retrieve value just set");
147}
148
149void
150EnvVarTestCase::UnsetVariable(const std::string& where)
151{
153 bool ok = EnvironmentVariable::Unset(where);
154 NS_TEST_EXPECT_MSG_EQ(ok, true, where << ": failed to unset variable");
155}
156
157void
158EnvVarTestCase::Check(const std::string& where, const std::string& envValue, KeyValueStore expect)
159{
161
162 // Print the expect and which ones were found in dict
163 std::cout << "\n"
164 << where << " variable: '" << envValue << "', expect[" << expect.size() << "]"
165 << ", dict[" << dict.size() << "]\n";
166
167 NS_TEST_EXPECT_MSG_EQ(dict.size(), expect.size(), where << ": unequal dictionary sizes");
168
169 std::size_t i{0};
170 for (const auto& kv : expect)
171 {
172 std::cout << " [" << i++ << "] '" << kv.first << "'\t'" << kv.second << "'";
173
174 auto loc = dict.find(kv.first);
175 bool found = loc != dict.end();
176 std::cout << (found ? "\tfound" : "\tNOT FOUND");
177 NS_TEST_EXPECT_MSG_EQ(found, true, where << ": expected key not found: " << kv.second);
178
179 if (found)
180 {
181 bool match = kv.second == loc->second;
182 if (match)
183 {
184 std::cout << ", match";
185 }
186 else
187 {
188 std::cout << ", NO MATCH: '" << loc->second << "'";
189 }
190 NS_TEST_EXPECT_MSG_EQ(kv.second, loc->second, where << ": key found, value mismatch");
191 }
192 std::cout << "\n";
193 ++i;
194 }
195
196 // Now just check dict for unexpected values
197 i = 0;
198 bool first{true};
199 for (const auto& kv : dict)
200 {
201 bool found = expect.find(kv.first) != expect.end();
202 if (!found)
203 {
204 std::cout << (first ? "Unexpected keys:" : "");
205 first = false;
206 std::cout << " [" << i << "] '" << kv.first << "'\t'" << kv.second << "'"
207 << " unexpected key, value\n";
208 }
209 ++i;
210 }
211}
212
213void
214EnvVarTestCase::SetAndCheck(const std::string& where,
215 const std::string& envValue,
216 KeyValueStore expect)
217{
218 SetVariable(where, envValue);
219 Check(where, envValue, expect);
220}
221
222void
223EnvVarTestCase::CheckGet(const std::string& where, const std::string& key, KeyFoundType expect)
224{
225 auto [found, value] = EnvironmentVariable::Get(m_variable, key, m_delimiter);
227 expect.first,
228 where << ": key '" << key << "' " << (expect.first ? "not " : "")
229 << "found unexpectedly");
231 expect.second,
232 where << ": incorrect value for key '" << key << "'");
233}
234
235void
236EnvVarTestCase::SetCheckAndGet(const std::string& where,
237 const std::string& envValue,
238 KeyValueStore expectDict,
239 const std::string& key,
240 KeyFoundType expectValue)
241{
242 SetAndCheck(where, envValue, expectDict);
243 CheckGet(where, key, expectValue);
244}
245
246void
248{
249 // Environment variable not set.
250 UnsetVariable("unset");
251 Check("unset", "", {});
252 auto [found, value] = EnvironmentVariable::Get(m_variable);
253 NS_TEST_EXPECT_MSG_EQ(found, false, "unset: variable found when not set");
254 NS_TEST_EXPECT_MSG_EQ(value.empty(), true, "unset: non-empty value from unset variable");
255
256 // Variable set but empty
257#ifndef __WIN32__
258 // Windows doesn't support environment variables with empty values
259 SetCheckAndGet("empty", "", {}, "", {true, ""});
260#endif
261
262 // Key not in variable
263 SetCheckAndGet("no-key",
264 "not|the|right=value",
265 {{"not", ""}, {"the", ""}, {"right", "value"}},
266 "key",
267 {false, ""});
268
269 // Key only (no delimiter): "key"
270 SetCheckAndGet("key-only", "key", {{"key", ""}}, "key", {true, ""});
271
272 // Extra delimiter: ":key", "key:"
273 SetCheckAndGet("front-|", "|key", {{"key", ""}}, "key", {true, ""});
274 SetCheckAndGet("back-|", "key|", {{"key", ""}}, "key", {true, ""});
275
276 // Double delimiter: "||key", "key||"
277 SetCheckAndGet("front-||", "||key", {{"key", ""}}, "key", {true, ""});
278 SetCheckAndGet("back-||", "key||", {{"key", ""}}, "key", {true, ""});
279
280 // Two keys: "key1|key2"
281 SetCheckAndGet("two keys", "key1|key2", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
282 CheckGet("two keys", "key2", {true, ""});
283
284 // Extra/double delimiters| "||key1|key2", "|key1|key2", "key1||key2", "key1|key2|",
285 // "key1|key2||"
286 SetCheckAndGet("||two keys", "||key1|key2", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
287 CheckGet("||two keys", "key2", {true, ""});
288 SetCheckAndGet("two keys||", "key1|key2||", {{"key1", ""}, {"key2", ""}}, "key1", {true, ""});
289 CheckGet("two keys||", "key2", {true, ""});
290
291 // Key=value: "key=value"
292 SetCheckAndGet("key-val", "key=value", {{"key", "value"}}, "key", {true, "value"});
293
294 // Mixed key-only, key=value| "key1|key2=|key3|key4=value"
295 SetCheckAndGet("mixed",
296 "key1|key2=value|key3|key4=value",
297 {{"key1", ""}, {"key2", "value"}, {"key3", ""}, {"key4", "value"}},
298 "key1",
299 {true, ""});
300 CheckGet("mixed", "key2", {true, "value"});
301 CheckGet("mixed", "key3", {true, ""});
302 CheckGet("mixed", "key4", {true, "value"});
303
304 // Empty/missing value| "key="
305 SetCheckAndGet("key=", "key=", {{"key", ""}}, "key", {true, ""});
306
307 // Extra `=`| "key==value"
308 SetCheckAndGet("key==", "key==", {{"key", "="}}, "key", {true, "="});
309
310 // Finish last line of verbose output
311 std::cout << std::endl;
312}
313
320{
321 public:
323};
324
326 : TestSuite("environment-variables")
327{
329}
330
336
337} // namespace tests
338
339} // 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:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
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:667
#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:252
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.