GDB (xrefs)

environ-selftests.c
Go to the documentation of this file.
1 /* Self tests for gdb_environ for GDB, the GNU debugger.
2
3 Copyright (C) 2017-2018 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21 #include "selftest.h"
22 #include "common/environ.h"
23 #include "common/diagnostics.h"
24
25 static const char gdb_selftest_env_var[] = "GDB_SELFTEST_ENVIRON";
26
27 static bool
28 set_contains (const std::set<std::string> &set, std::string key)
29 {
30 return set.find (key) != set.end ();
31 }
32
33 namespace selftests {
34 namespace gdb_environ_tests {
35
36 /* Test if the vector is initialized in a correct way. */
37
38 static void
39 test_vector_initialization ()
40 {
41 gdb_environ env;
42
43 /* When the vector is initialized, there should always be one NULL
44 element in it. */
45 SELF_CHECK (env.envp ()[0] == NULL);
46 SELF_CHECK (env.user_set_env ().size () == 0);
47 SELF_CHECK (env.user_unset_env ().size () == 0);
48
49 /* Make sure that there is no other element. */
50 SELF_CHECK (env.get ("PWD") == NULL);
51 }
52
53 /* Test initialization using the host's environ. */
54
55 static void
56 test_init_from_host_environ ()
57 {
58 /* Initialize the environment vector using the host's environ. */
59 gdb_environ env = gdb_environ::from_host_environ ();
60
61 /* The user-set and user-unset lists must be empty. */
62 SELF_CHECK (env.user_set_env ().size () == 0);
63 SELF_CHECK (env.user_unset_env ().size () == 0);
64
65 /* Our test environment variable should be present at the
66 vector. */
67 SELF_CHECK (strcmp (env.get (gdb_selftest_env_var), "1") == 0);
68 }
69
70 /* Test reinitialization using the host's environ. */
71
72 static void
73 test_reinit_from_host_environ ()
74 {
75 /* Reinitialize our environ vector using the host environ. We
76 should be able to see one (and only one) instance of the test
77 variable. */
78 gdb_environ env = gdb_environ::from_host_environ ();
79 env = gdb_environ::from_host_environ ();
80 char **envp = env.envp ();
81 int num_found = 0;
82
83 for (size_t i = 0; envp[i] != NULL; ++i)
84 if (strcmp (envp[i], "GDB_SELFTEST_ENVIRON=1") == 0)
85 ++num_found;
86 SELF_CHECK (num_found == 1);
87 }
88
89 /* Test the case when we set a variable A, then set a variable B,
90 then unset A, and make sure that we cannot find A in the environ
91 vector, but can still find B. */
92
93 static void
94 test_set_A_unset_B_unset_A_cannot_find_A_can_find_B ()
95 {
96 gdb_environ env;
97
98 env.set ("GDB_SELFTEST_ENVIRON_1", "aaa");
99 SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON_1"), "aaa") == 0);
100 /* User-set environ var list must contain one element. */
101 SELF_CHECK (env.user_set_env ().size () == 1);
102 SELF_CHECK (set_contains (env.user_set_env (),
103 std::string ("GDB_SELFTEST_ENVIRON_1=aaa")));
104
105 env.set ("GDB_SELFTEST_ENVIRON_2", "bbb");
106 SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON_2"), "bbb") == 0);
107
108 env.unset ("GDB_SELFTEST_ENVIRON_1");
109 SELF_CHECK (env.get ("GDB_SELFTEST_ENVIRON_1") == NULL);
110 SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON_2"), "bbb") == 0);
111
112 /* The user-set environ var list must contain only one element
113 now. */
114 SELF_CHECK (set_contains (env.user_set_env (),
115 std::string ("GDB_SELFTEST_ENVIRON_2=bbb")));
116 SELF_CHECK (env.user_set_env ().size () == 1);
117 }
118
119 /* Check if unset followed by a set in an empty vector works. */
120
121 static void
122 test_unset_set_empty_vector ()
123 {
124 gdb_environ env;
125
126 env.set ("PWD", "test");
127 SELF_CHECK (strcmp (env.get ("PWD"), "test") == 0);
128 SELF_CHECK (set_contains (env.user_set_env (), std::string ("PWD=test")));
129 SELF_CHECK (env.user_unset_env ().size () == 0);
130 /* The second element must be NULL. */
131 SELF_CHECK (env.envp ()[1] == NULL);
132 SELF_CHECK (env.user_set_env ().size () == 1);
133 env.unset ("PWD");
134 SELF_CHECK (env.envp ()[0] == NULL);
135 SELF_CHECK (env.user_set_env ().size () == 0);
136 SELF_CHECK (env.user_unset_env ().size () == 1);
137 SELF_CHECK (set_contains (env.user_unset_env (), std::string ("PWD")));
138 }
139
140 /* When we clear our environ vector, there should be only one
141 element on it (NULL), and we shouldn't be able to get our test
142 variable. */
143
144 static void
145 test_vector_clear ()
146 {
147 gdb_environ env;
148
149 env.set (gdb_selftest_env_var, "1");
150
151 env.clear ();
152 SELF_CHECK (env.envp ()[0] == NULL);
153 SELF_CHECK (env.user_set_env ().size () == 0);
154 SELF_CHECK (env.user_unset_env ().size () == 0);
155 SELF_CHECK (env.get (gdb_selftest_env_var) == NULL);
156 }
157
158 /* Test that after a std::move the moved-from object is left at a
159 valid state (i.e., its only element is NULL). */
160
161 static void
162 test_std_move ()
163 {
164 gdb_environ env;
165 gdb_environ env2;
166
167 env.set ("A", "1");
168 SELF_CHECK (strcmp (env.get ("A"), "1") == 0);
169 SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1")));
170 SELF_CHECK (env.user_set_env ().size () == 1);
171
172 env2 = std::move (env);
173 SELF_CHECK (env.envp ()[0] == NULL);
174 SELF_CHECK (strcmp (env2.get ("A"), "1") == 0);
175 SELF_CHECK (env2.envp ()[1] == NULL);
176 SELF_CHECK (env.user_set_env ().size () == 0);
177 SELF_CHECK (set_contains (env2.user_set_env (), std::string ("A=1")));
178 SELF_CHECK (env2.user_set_env ().size () == 1);
179 env.set ("B", "2");
180 SELF_CHECK (strcmp (env.get ("B"), "2") == 0);
181 SELF_CHECK (env.envp ()[1] == NULL);
182 }
183
184 /* Test that the move constructor leaves everything at a valid
185 state. */
186
187 static void
188 test_move_constructor ()
189 {
190 gdb_environ env;
191
192 env.set ("A", "1");
193 SELF_CHECK (strcmp (env.get ("A"), "1") == 0);
194 SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1")));
195
196 gdb_environ env2 = std::move (env);
197 SELF_CHECK (env.envp ()[0] == NULL);
198 SELF_CHECK (env.user_set_env ().size () == 0);
199 SELF_CHECK (strcmp (env2.get ("A"), "1") == 0);
200 SELF_CHECK (env2.envp ()[1] == NULL);
201 SELF_CHECK (set_contains (env2.user_set_env (), std::string ("A=1")));
202 SELF_CHECK (env2.user_set_env ().size () == 1);
203
204 env.set ("B", "2");
205 SELF_CHECK (strcmp (env.get ("B"), "2") == 0);
206 SELF_CHECK (env.envp ()[1] == NULL);
207 SELF_CHECK (set_contains (env.user_set_env (), std::string ("B=2")));
208 SELF_CHECK (env.user_set_env ().size () == 1);
209 }
210
211 /* Test that self-moving works. */
212
213 static void
214 test_self_move ()
215 {
216 gdb_environ env;
217
218 /* Test self-move. */
219 env.set ("A", "1");
220 SELF_CHECK (strcmp (env.get ("A"), "1") == 0);
221 SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1")));
222 SELF_CHECK (env.user_set_env ().size () == 1);
223
224 /* Some compilers warn about moving to self, but that's precisely what we want
225 to test here, so turn this warning off. */
226 DIAGNOSTIC_PUSH
227 DIAGNOSTIC_IGNORE_SELF_MOVE
228 env = std::move (env);
229 DIAGNOSTIC_POP
230
231 SELF_CHECK (strcmp (env.get ("A"), "1") == 0);
232 SELF_CHECK (strcmp (env.envp ()[0], "A=1") == 0);
233 SELF_CHECK (env.envp ()[1] == NULL);
234 SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1")));
235 SELF_CHECK (env.user_set_env ().size () == 1);
236 }
237
238 /* Test if set/unset/reset works. */
239
240 static void
241 test_set_unset_reset ()
242 {
243 gdb_environ env = gdb_environ::from_host_environ ();
244
245 /* Our test variable should already be present in the host's environment. */
246 SELF_CHECK (env.get ("GDB_SELFTEST_ENVIRON") != NULL);
247
248 /* Set our test variable to another value. */
249 env.set ("GDB_SELFTEST_ENVIRON", "test");
250 SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON"), "test") == 0);
251 SELF_CHECK (env.user_set_env ().size () == 1);
252 SELF_CHECK (env.user_unset_env ().size () == 0);
253
254 /* And unset our test variable. The variable still exists in the
255 host's environment, but doesn't exist in our vector. */
256 env.unset ("GDB_SELFTEST_ENVIRON");
257 SELF_CHECK (env.get ("GDB_SELFTEST_ENVIRON") == NULL);
258 SELF_CHECK (env.user_set_env ().size () == 0);
259 SELF_CHECK (env.user_unset_env ().size () == 1);
260 SELF_CHECK (set_contains (env.user_unset_env (),
261 std::string ("GDB_SELFTEST_ENVIRON")));
262
263 /* Re-set the test variable. */
264 env.set ("GDB_SELFTEST_ENVIRON", "1");
265 SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON"), "1") == 0);
266 }
267
268 static void
269 run_tests ()
270 {
271 /* Set a test environment variable. */
272 if (setenv ("GDB_SELFTEST_ENVIRON", "1", 1) != 0)
273 error (_("Could not set environment variable for testing."));
274
275 test_vector_initialization ();
276
277 test_unset_set_empty_vector ();
278
279 test_init_from_host_environ ();
280
281 test_set_unset_reset ();
282
283 test_vector_clear ();
284
285 test_reinit_from_host_environ ();
286
287 /* Get rid of our test variable. We won't need it anymore. */
288 unsetenv ("GDB_SELFTEST_ENVIRON");
289
290 test_set_A_unset_B_unset_A_cannot_find_A_can_find_B ();
291
292 test_std_move ();
293
294 test_move_constructor ();
295
296 test_self_move ();
297 }
298 } /* namespace gdb_environ */
299 } /* namespace selftests */
300
301 void
302 _initialize_environ_selftests ()
303 {
304 selftests::register_test ("gdb_environ",
305 selftests::gdb_environ_tests::run_tests);
306 }
string
const char * string
Definition: signals.c:50
gdb_environ::get
const char * get(const char *var) const
Definition: environ.c:92
gdb_environ
Definition: environ.h:26
selftests::gdb_environ_tests::test_self_move
static void test_self_move()
Definition: environ-selftests.c:214
_initialize_environ_selftests
void _initialize_environ_selftests()
Definition: environ-selftests.c:302
gdb_environ::set
void set(const char *var, const char *value)
Definition: environ.c:106
selftests::gdb_environ_tests::test_set_unset_reset
static void test_set_unset_reset()
Definition: environ-selftests.c:241
selftests::gdb_environ_tests::test_reinit_from_host_environ
static void test_reinit_from_host_environ()
Definition: environ-selftests.c:73
_
#define _(String)
Definition: gdb_locale.h:35
defs.h
gdb_environ::from_host_environ
static gdb_environ from_host_environ()
Definition: environ.c:44
DIAGNOSTIC_IGNORE_SELF_MOVE
#define DIAGNOSTIC_IGNORE_SELF_MOVE
Definition: diagnostics.h:57
gdb_environ::user_unset_env
const std::set< std::string > & user_unset_env() const
Definition: environ.c:180
selftests
Definition: selftest.c:25
selftests::gdb_environ_tests::test_set_A_unset_B_unset_A_cannot_find_A_can_find_B
static void test_set_A_unset_B_unset_A_cannot_find_A_can_find_B()
Definition: environ-selftests.c:94
selftests::gdb_environ_tests::test_init_from_host_environ
static void test_init_from_host_environ()
Definition: environ-selftests.c:56
selftests::gdb_environ_tests::test_vector_initialization
static void test_vector_initialization()
Definition: environ-selftests.c:39
DIAGNOSTIC_PUSH
#define DIAGNOSTIC_PUSH
Definition: diagnostics.h:29
gdb_environ::clear
void clear()
Definition: environ.c:65
diagnostics.h
selftests::gdb_environ_tests::run_tests
static void run_tests()
Definition: environ-selftests.c:269
environ.h
gdb_selftest_env_var
static const char gdb_selftest_env_var[]
Definition: environ-selftests.c:25
selftests::gdb_environ_tests::test_std_move
static void test_std_move()
Definition: environ-selftests.c:162
gdb_environ::user_set_env
const std::set< std::string > & user_set_env() const
Definition: environ.c:174
gdb_environ::envp
char ** envp() const
Definition: environ.c:166
gdb_environ::unset
void unset(const char *var)
Definition: environ.c:158
selftest.h
set_contains
static bool set_contains(const std::set< std::string > &set, std::string key)
Definition: environ-selftests.c:28
selftests::gdb_environ_tests::test_unset_set_empty_vector
static void test_unset_set_empty_vector()
Definition: environ-selftests.c:122
DIAGNOSTIC_POP
#define DIAGNOSTIC_POP
Definition: diagnostics.h:30
selftests::register_test
void register_test(const std::string &name, selftest *test)
Definition: selftest.c:52
error
void error(const char *fmt,...)
Definition: errors.c:38
selftests::gdb_environ_tests::test_vector_clear
static void test_vector_clear()
Definition: environ-selftests.c:145
selftests::gdb_environ_tests::test_move_constructor
static void test_move_constructor()
Definition: environ-selftests.c:188
SELF_CHECK
#define SELF_CHECK(VALUE)
Definition: selftest.h:67