Commit | Line | Data |
---|---|---|
9a6c7d9c SDJ |
1 | /* Self tests for gdb_environ for GDB, the GNU debugger. |
2 | ||
b811d2c2 | 3 | Copyright (C) 2017-2020 Free Software Foundation, Inc. |
9a6c7d9c SDJ |
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" | |
268a13a5 TT |
21 | #include "gdbsupport/selftest.h" |
22 | #include "gdbsupport/environ.h" | |
e9cb46ab | 23 | #include "diagnostics.h" |
9a6c7d9c | 24 | |
0a2dde4a SDJ |
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 | ||
9a6c7d9c SDJ |
33 | namespace selftests { |
34 | namespace gdb_environ_tests { | |
35 | ||
0a2dde4a SDJ |
36 | /* Test if the vector is initialized in a correct way. */ |
37 | ||
9a6c7d9c | 38 | static void |
0a2dde4a | 39 | test_vector_initialization () |
9a6c7d9c | 40 | { |
9a6c7d9c SDJ |
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); | |
0a2dde4a SDJ |
46 | SELF_CHECK (env.user_set_env ().size () == 0); |
47 | SELF_CHECK (env.user_unset_env ().size () == 0); | |
9a6c7d9c SDJ |
48 | |
49 | /* Make sure that there is no other element. */ | |
50 | SELF_CHECK (env.get ("PWD") == NULL); | |
0a2dde4a | 51 | } |
9a6c7d9c | 52 | |
0a2dde4a | 53 | /* Test initialization using the host's environ. */ |
9a6c7d9c | 54 | |
0a2dde4a SDJ |
55 | static void |
56 | test_init_from_host_environ () | |
57 | { | |
9a6c7d9c | 58 | /* Initialize the environment vector using the host's environ. */ |
0a2dde4a SDJ |
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); | |
9a6c7d9c SDJ |
64 | |
65 | /* Our test environment variable should be present at the | |
66 | vector. */ | |
0a2dde4a SDJ |
67 | SELF_CHECK (strcmp (env.get (gdb_selftest_env_var), "1") == 0); |
68 | } | |
9a6c7d9c | 69 | |
0a2dde4a | 70 | /* Test reinitialization using the host's environ. */ |
9a6c7d9c | 71 | |
0a2dde4a SDJ |
72 | static void |
73 | test_reinit_from_host_environ () | |
74 | { | |
9a6c7d9c SDJ |
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. */ | |
0a2dde4a | 78 | gdb_environ env = gdb_environ::from_host_environ (); |
9a6c7d9c SDJ |
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); | |
0a2dde4a | 87 | } |
9a6c7d9c | 88 | |
0a2dde4a SDJ |
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; | |
9a6c7d9c | 97 | |
9a6c7d9c SDJ |
98 | env.set ("GDB_SELFTEST_ENVIRON_1", "aaa"); |
99 | SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON_1"), "aaa") == 0); | |
0a2dde4a SDJ |
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"))); | |
9a6c7d9c SDJ |
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 | ||
0a2dde4a SDJ |
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 | ||
9a6c7d9c | 151 | env.clear (); |
0a2dde4a SDJ |
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; | |
9a6c7d9c | 166 | |
9a6c7d9c SDJ |
167 | env.set ("A", "1"); |
168 | SELF_CHECK (strcmp (env.get ("A"), "1") == 0); | |
0a2dde4a SDJ |
169 | SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1"))); |
170 | SELF_CHECK (env.user_set_env ().size () == 1); | |
171 | ||
9a6c7d9c SDJ |
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); | |
0a2dde4a SDJ |
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); | |
9a6c7d9c SDJ |
179 | env.set ("B", "2"); |
180 | SELF_CHECK (strcmp (env.get ("B"), "2") == 0); | |
181 | SELF_CHECK (env.envp ()[1] == NULL); | |
0a2dde4a SDJ |
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; | |
9a6c7d9c | 191 | |
9a6c7d9c SDJ |
192 | env.set ("A", "1"); |
193 | SELF_CHECK (strcmp (env.get ("A"), "1") == 0); | |
0a2dde4a SDJ |
194 | SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1"))); |
195 | ||
196 | gdb_environ env2 = std::move (env); | |
9a6c7d9c | 197 | SELF_CHECK (env.envp ()[0] == NULL); |
0a2dde4a SDJ |
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 | ||
9a6c7d9c SDJ |
204 | env.set ("B", "2"); |
205 | SELF_CHECK (strcmp (env.get ("B"), "2") == 0); | |
206 | SELF_CHECK (env.envp ()[1] == NULL); | |
0a2dde4a SDJ |
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; | |
9a6c7d9c SDJ |
217 | |
218 | /* Test self-move. */ | |
9a6c7d9c SDJ |
219 | env.set ("A", "1"); |
220 | SELF_CHECK (strcmp (env.get ("A"), "1") == 0); | |
0a2dde4a SDJ |
221 | SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1"))); |
222 | SELF_CHECK (env.user_set_env ().size () == 1); | |
f4906a9a PA |
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 | |
9a6c7d9c | 228 | env = std::move (env); |
f4906a9a PA |
229 | DIAGNOSTIC_POP |
230 | ||
9a6c7d9c SDJ |
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); | |
0a2dde4a SDJ |
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 (); | |
9a6c7d9c SDJ |
297 | } |
298 | } /* namespace gdb_environ */ | |
299 | } /* namespace selftests */ | |
300 | ||
6c265988 | 301 | void _initialize_environ_selftests (); |
9a6c7d9c SDJ |
302 | void |
303 | _initialize_environ_selftests () | |
304 | { | |
1526853e SM |
305 | selftests::register_test ("gdb_environ", |
306 | selftests::gdb_environ_tests::run_tests); | |
9a6c7d9c | 307 | } |