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
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
57 {
58  /* Initialize the environment vector using the host's 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
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. */
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
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);
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. */
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
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);
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
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
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
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
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. */
228  env = std::move (env);
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
242 {
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);
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
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 
276 
278 
280 
282 
284 
286 
287  /* Get rid of our test variable. We won't need it anymore. */
288  unsetenv ("GDB_SELFTEST_ENVIRON");
289 
291 
292  test_std_move ();
293 
295 
296  test_self_move ();
297 }
298 } /* namespace gdb_environ */
299 } /* namespace selftests */
300 
301 void
303 {
304  selftests::register_test ("gdb_environ",
306 }
const char * string
Definition: signals.c:50
const char * get(const char *var) const
Definition: environ.c:92
void _initialize_environ_selftests()
void set(const char *var, const char *value)
Definition: environ.c:106
static void test_reinit_from_host_environ()
#define _(String)
Definition: gdb_locale.h:35
static gdb_environ from_host_environ()
Definition: environ.c:44
#define DIAGNOSTIC_IGNORE_SELF_MOVE
Definition: diagnostics.h:57
const std::set< std::string > & user_unset_env() const
Definition: environ.c:180
static void test_set_A_unset_B_unset_A_cannot_find_A_can_find_B()
static void test_init_from_host_environ()
static void test_vector_initialization()
#define DIAGNOSTIC_PUSH
Definition: diagnostics.h:29
void clear()
Definition: environ.c:65
static const char gdb_selftest_env_var[]
const std::set< std::string > & user_set_env() const
Definition: environ.c:174
char ** envp() const
Definition: environ.c:166
void unset(const char *var)
Definition: environ.c:158
static bool set_contains(const std::set< std::string > &set, std::string key)
#define DIAGNOSTIC_POP
Definition: diagnostics.h:30
void register_test(const std::string &name, selftest *test)
Definition: selftest.c:52
void error(const char *fmt,...)
Definition: errors.c:38
#define SELF_CHECK(VALUE)
Definition: selftest.h:67