]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/ceph_argparse.cc
update sources to v12.2.3
[ceph.git] / ceph / src / test / ceph_argparse.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include "common/ceph_argparse.h"
16
17 #include "gtest/gtest.h"
18 #include <vector>
19
20 /* Holds a std::vector with C-strings.
21 * Will free() them properly in the destructor.
22 *
23 * Note: the ceph_argparse functions modify the vector, removing elements as
24 * they find them. So we keep a parallel vector, orig, to make sure that we
25 * never forget to delete a string.
26 */
27 class VectorContainer
28 {
29 public:
30 explicit VectorContainer(const char** arr_) {
31 for (const char **a = arr_; *a; ++a) {
32 const char *str = (const char*)strdup(*a);
33 arr.push_back(str);
34 orig.push_back(str);
35 }
36 }
37 ~VectorContainer() {
38 for (std::vector<const char*>::iterator i = orig.begin();
39 i != orig.end(); ++i)
40 {
41 free((void*)*i);
42 }
43 }
44 void refresh() {
45 arr.assign(orig.begin(), orig.end());
46 }
47 std::vector < const char* > arr;
48
49 private:
50 std::vector < const char* > orig;
51 };
52
53 TEST(CephArgParse, SimpleArgParse) {
54 const char *BAR5[] = { "./myprog", "--bar", "5", NULL };
55 const char *FOO[] = { "./myprog", "--foo", "--baz", NULL };
56 const char *NONE[] = { "./myprog", NULL };
57
58 bool found_foo = false;
59 std::string found_bar;
60 VectorContainer bar5(BAR5);
61 for (std::vector<const char*>::iterator i = bar5.arr.begin();
62 i != bar5.arr.end(); )
63 {
64 if (ceph_argparse_flag(bar5.arr, i, "--foo", (char*)NULL)) {
65 found_foo = true;
66 }
67 else if (ceph_argparse_witharg(bar5.arr, i, &found_bar, "--bar", (char*)NULL)) {
68 }
69 else
70 ++i;
71 }
72 ASSERT_EQ(found_foo, false);
73 ASSERT_EQ(found_bar, "5");
74
75 found_foo = false;
76 found_bar = "";
77 bool baz_found = false;
78 std::string found_baz = "";
79 VectorContainer foo(FOO);
80 ostringstream err;
81 for (std::vector<const char*>::iterator i = foo.arr.begin();
82 i != foo.arr.end(); )
83 {
84 if (ceph_argparse_flag(foo.arr, i, "--foo", (char*)NULL)) {
85 found_foo = true;
86 }
87 else if (ceph_argparse_witharg(foo.arr, i, &found_bar, "--bar", (char*)NULL)) {
88 }
89 else if (ceph_argparse_witharg(foo.arr, i, &found_baz, err, "--baz", (char*)NULL)) {
90 ASSERT_NE(string(""), err.str());
91 baz_found = true;
92 }
93 else
94 ++i;
95 }
96 ASSERT_EQ(found_foo, true);
97 ASSERT_EQ(found_bar, "");
98 ASSERT_EQ(baz_found, true);
99 ASSERT_EQ(found_baz, "");
100
101 found_foo = false;
102 found_bar = "";
103 VectorContainer none(NONE);
104 for (std::vector<const char*>::iterator i = none.arr.begin();
105 i != none.arr.end(); )
106 {
107 if (ceph_argparse_flag(none.arr, i, "--foo", (char*)NULL)) {
108 found_foo = true;
109 }
110 else if (ceph_argparse_witharg(none.arr, i, &found_bar, "--bar", (char*)NULL)) {
111 }
112 else
113 ++i;
114 }
115 ASSERT_EQ(found_foo, false);
116 ASSERT_EQ(found_bar, "");
117 }
118
119 TEST(CephArgParse, DoubleDash) {
120 const char *ARGS[] = { "./myprog", "--foo", "5", "--", "--bar", "6", NULL };
121
122 int foo = -1, bar = -1;
123 VectorContainer args(ARGS);
124 for (std::vector<const char*>::iterator i = args.arr.begin();
125 i != args.arr.end(); )
126 {
127 std::string myarg;
128 if (ceph_argparse_double_dash(args.arr, i)) {
129 break;
130 }
131 else if (ceph_argparse_witharg(args.arr, i, &myarg, "--foo", (char*)NULL)) {
132 foo = atoi(myarg.c_str());
133 }
134 else if (ceph_argparse_witharg(args.arr, i, &myarg, "--bar", (char*)NULL)) {
135 bar = atoi(myarg.c_str());
136 }
137 else
138 ++i;
139 }
140 ASSERT_EQ(foo, 5);
141 ASSERT_EQ(bar, -1);
142 }
143
144
145 TEST(CephArgParse, WithDashesAndUnderscores) {
146 const char *BAZSTUFF1[] = { "./myprog", "--goo", "--baz-stuff", "50", "--end", NULL };
147 const char *BAZSTUFF2[] = { "./myprog", "--goo2", "--baz_stuff", "50", NULL };
148 const char *BAZSTUFF3[] = { "./myprog", "--goo2", "--baz-stuff=50", "50", NULL };
149 const char *BAZSTUFF4[] = { "./myprog", "--goo2", "--baz_stuff=50", "50", NULL };
150 const char *NONE1[] = { "./myprog", NULL };
151 const char *NONE2[] = { "./myprog", "--goo2", "--baz_stuff2", "50", NULL };
152 const char *NONE3[] = { "./myprog", "--goo2", "__baz_stuff", "50", NULL };
153
154 // as flag
155 std::string found_baz;
156 VectorContainer bazstuff1(BAZSTUFF1);
157 for (std::vector<const char*>::iterator i = bazstuff1.arr.begin();
158 i != bazstuff1.arr.end(); )
159 {
160 if (ceph_argparse_flag(bazstuff1.arr, i, "--baz-stuff", (char*)NULL)) {
161 found_baz = "true";
162 }
163 else
164 ++i;
165 }
166 ASSERT_EQ(found_baz, "true");
167
168 // as flag
169 found_baz = "";
170 VectorContainer bazstuff2(BAZSTUFF2);
171 for (std::vector<const char*>::iterator i = bazstuff2.arr.begin();
172 i != bazstuff2.arr.end(); )
173 {
174 if (ceph_argparse_flag(bazstuff2.arr, i, "--baz-stuff", (char*)NULL)) {
175 found_baz = "true";
176 }
177 else
178 ++i;
179 }
180 ASSERT_EQ(found_baz, "true");
181
182 // with argument
183 found_baz = "";
184 bazstuff1.refresh();
185 for (std::vector<const char*>::iterator i = bazstuff1.arr.begin();
186 i != bazstuff1.arr.end(); )
187 {
188 if (ceph_argparse_witharg(bazstuff1.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
189 }
190 else
191 ++i;
192 }
193 ASSERT_EQ(found_baz, "50");
194
195 // with argument
196 found_baz = "";
197 bazstuff2.refresh();
198 for (std::vector<const char*>::iterator i = bazstuff2.arr.begin();
199 i != bazstuff2.arr.end(); )
200 {
201 if (ceph_argparse_witharg(bazstuff2.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
202 }
203 else
204 ++i;
205 }
206 ASSERT_EQ(found_baz, "50");
207
208 // with argument
209 found_baz = "";
210 VectorContainer bazstuff3(BAZSTUFF3);
211 for (std::vector<const char*>::iterator i = bazstuff3.arr.begin();
212 i != bazstuff3.arr.end(); )
213 {
214 if (ceph_argparse_witharg(bazstuff3.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
215 }
216 else
217 ++i;
218 }
219 ASSERT_EQ(found_baz, "50");
220
221 // with argument
222 found_baz = "";
223 VectorContainer bazstuff4(BAZSTUFF4);
224 for (std::vector<const char*>::iterator i = bazstuff4.arr.begin();
225 i != bazstuff4.arr.end(); )
226 {
227 if (ceph_argparse_witharg(bazstuff4.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
228 }
229 else
230 ++i;
231 }
232 ASSERT_EQ(found_baz, "50");
233
234 // not found
235 found_baz = "";
236 VectorContainer none1(NONE1);
237 for (std::vector<const char*>::iterator i = none1.arr.begin();
238 i != none1.arr.end(); )
239 {
240 if (ceph_argparse_flag(none1.arr, i, "--baz-stuff", (char*)NULL)) {
241 found_baz = "true";
242 }
243 else if (ceph_argparse_witharg(none1.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
244 }
245 else
246 ++i;
247 }
248 ASSERT_EQ(found_baz, "");
249
250 // not found
251 found_baz = "";
252 VectorContainer none2(NONE2);
253 for (std::vector<const char*>::iterator i = none2.arr.begin();
254 i != none2.arr.end(); )
255 {
256 if (ceph_argparse_flag(none2.arr, i, "--baz-stuff", (char*)NULL)) {
257 found_baz = "true";
258 }
259 else if (ceph_argparse_witharg(none2.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
260 }
261 else
262 ++i;
263 }
264 ASSERT_EQ(found_baz, "");
265
266 // not found
267 found_baz = "";
268 VectorContainer none3(NONE3);
269 for (std::vector<const char*>::iterator i = none3.arr.begin();
270 i != none3.arr.end(); )
271 {
272 if (ceph_argparse_flag(none3.arr, i, "--baz-stuff", (char*)NULL)) {
273 found_baz = "true";
274 }
275 else if (ceph_argparse_witharg(none3.arr, i, &found_baz, "--baz-stuff", (char*)NULL)) {
276 }
277 else
278 ++i;
279 }
280 ASSERT_EQ(found_baz, "");
281 }
282
283 TEST(CephArgParse, WithFloat) {
284 const char *BAZSTUFF1[] = { "./myprog", "--foo", "50.5", "--bar", "52", NULL };
285
286 VectorContainer bazstuff1(BAZSTUFF1);
287 ostringstream err;
288 float foo;
289 int bar = -1;
290 for (std::vector<const char*>::iterator i = bazstuff1.arr.begin();
291 i != bazstuff1.arr.end(); )
292 {
293 if (ceph_argparse_double_dash(bazstuff1.arr, i)) {
294 break;
295 } else if (ceph_argparse_witharg(bazstuff1.arr, i, &foo, err, "--foo", (char*)NULL)) {
296 ASSERT_EQ(string(""), err.str());
297 } else if (ceph_argparse_witharg(bazstuff1.arr, i, &bar, err, "--bar", (char*)NULL)) {
298 ASSERT_EQ(string(""), err.str());
299 }
300 else {
301 ++i;
302 }
303 }
304 ASSERT_EQ(foo, 50.5);
305 ASSERT_EQ(bar, 52);
306 }
307
308 TEST(CephArgParse, WithInt) {
309 const char *BAZSTUFF1[] = { "./myprog", "--foo", "50", "--bar", "52", NULL };
310 const char *BAZSTUFF2[] = { "./myprog", "--foo", "--bar", "52", NULL };
311 const char *BAZSTUFF3[] = { "./myprog", "--foo", "40", "--", "--bar", "42", NULL };
312
313 // normal test
314 VectorContainer bazstuff1(BAZSTUFF1);
315 ostringstream err;
316 int foo = -1, bar = -1;
317 for (std::vector<const char*>::iterator i = bazstuff1.arr.begin();
318 i != bazstuff1.arr.end(); )
319 {
320 if (ceph_argparse_double_dash(bazstuff1.arr, i)) {
321 break;
322 } else if (ceph_argparse_witharg(bazstuff1.arr, i, &foo, err, "--foo", (char*)NULL)) {
323 ASSERT_EQ(string(""), err.str());
324 } else if (ceph_argparse_witharg(bazstuff1.arr, i, &bar, err, "--bar", (char*)NULL)) {
325 ASSERT_EQ(string(""), err.str());
326 }
327 else {
328 ++i;
329 }
330 }
331 ASSERT_EQ(foo, 50);
332 ASSERT_EQ(bar, 52);
333
334 // parse error test
335 VectorContainer bazstuff2(BAZSTUFF2);
336 ostringstream err2;
337 for (std::vector<const char*>::iterator i = bazstuff2.arr.begin();
338 i != bazstuff2.arr.end(); )
339 {
340 if (ceph_argparse_double_dash(bazstuff2.arr, i)) {
341 break;
342 } else if (ceph_argparse_witharg(bazstuff2.arr, i, &foo, err2, "--foo", (char*)NULL)) {
343 ASSERT_NE(string(""), err2.str());
344 }
345 else {
346 ++i;
347 }
348 }
349
350 // double dash test
351 VectorContainer bazstuff3(BAZSTUFF3);
352 foo = -1, bar = -1;
353 for (std::vector<const char*>::iterator i = bazstuff3.arr.begin();
354 i != bazstuff3.arr.end(); )
355 {
356 if (ceph_argparse_double_dash(bazstuff3.arr, i)) {
357 break;
358 } else if (ceph_argparse_witharg(bazstuff3.arr, i, &foo, err, "--foo", (char*)NULL)) {
359 ASSERT_EQ(string(""), err.str());
360 } else if (ceph_argparse_witharg(bazstuff3.arr, i, &bar, err, "--bar", (char*)NULL)) {
361 ASSERT_EQ(string(""), err.str());
362 }
363 else {
364 ++i;
365 }
366 }
367 ASSERT_EQ(foo, 40);
368 ASSERT_EQ(bar, -1);
369 }
370
371 TEST(CephArgParse, env_to_vec) {
372 {
373 std::vector<const char*> args;
374 unsetenv("CEPH_ARGS");
375 unsetenv("WHATEVER");
376 clear_g_str_vec();
377 env_to_vec(args);
378 EXPECT_EQ(0u, args.size());
379 clear_g_str_vec();
380 env_to_vec(args, "WHATEVER");
381 EXPECT_EQ(0u, args.size());
382 args.push_back("a");
383 setenv("CEPH_ARGS", "b c", 0);
384 clear_g_str_vec();
385 env_to_vec(args);
386 EXPECT_EQ(3u, args.size());
387 EXPECT_EQ(string("b"), args[1]);
388 EXPECT_EQ(string("c"), args[2]);
389 setenv("WHATEVER", "d e", 0);
390 clear_g_str_vec();
391 env_to_vec(args, "WHATEVER");
392 EXPECT_EQ(5u, args.size());
393 EXPECT_EQ(string("d"), args[3]);
394 EXPECT_EQ(string("e"), args[4]);
395 }
396 {
397 std::vector<const char*> args;
398 unsetenv("CEPH_ARGS");
399 args.push_back("a");
400 args.push_back("--");
401 args.push_back("c");
402 setenv("CEPH_ARGS", "b -- d", 0);
403 clear_g_str_vec();
404 env_to_vec(args);
405 EXPECT_EQ(5u, args.size());
406 EXPECT_EQ(string("a"), args[0]);
407 EXPECT_EQ(string("b"), args[1]);
408 EXPECT_EQ(string("--"), args[2]);
409 EXPECT_EQ(string("c"), args[3]);
410 EXPECT_EQ(string("d"), args[4]);
411 }
412 {
413 std::vector<const char*> args;
414 unsetenv("CEPH_ARGS");
415 args.push_back("a");
416 args.push_back("--");
417 setenv("CEPH_ARGS", "b -- c", 0);
418 clear_g_str_vec();
419 env_to_vec(args);
420 EXPECT_EQ(4u, args.size());
421 EXPECT_EQ(string("a"), args[0]);
422 EXPECT_EQ(string("b"), args[1]);
423 EXPECT_EQ(string("--"), args[2]);
424 EXPECT_EQ(string("c"), args[3]);
425 }
426 {
427 std::vector<const char*> args;
428 unsetenv("CEPH_ARGS");
429 args.push_back("--");
430 args.push_back("c");
431 setenv("CEPH_ARGS", "b -- d", 0);
432 clear_g_str_vec();
433 env_to_vec(args);
434 EXPECT_EQ(4u, args.size());
435 EXPECT_EQ(string("b"), args[0]);
436 EXPECT_EQ(string("--"), args[1]);
437 EXPECT_EQ(string("c"), args[2]);
438 EXPECT_EQ(string("d"), args[3]);
439 }
440 {
441 std::vector<const char*> args;
442 unsetenv("CEPH_ARGS");
443 args.push_back("b");
444 setenv("CEPH_ARGS", "c -- d", 0);
445 clear_g_str_vec();
446 env_to_vec(args);
447 EXPECT_EQ(4u, args.size());
448 EXPECT_EQ(string("b"), args[0]);
449 EXPECT_EQ(string("c"), args[1]);
450 EXPECT_EQ(string("--"), args[2]);
451 EXPECT_EQ(string("d"), args[3]);
452 }
453 {
454 std::vector<const char*> args;
455 unsetenv("CEPH_ARGS");
456 args.push_back("a");
457 args.push_back("--");
458 args.push_back("c");
459 setenv("CEPH_ARGS", "-- d", 0);
460 clear_g_str_vec();
461 env_to_vec(args);
462 EXPECT_EQ(4u, args.size());
463 EXPECT_EQ(string("a"), args[0]);
464 EXPECT_EQ(string("--"), args[1]);
465 EXPECT_EQ(string("c"), args[2]);
466 EXPECT_EQ(string("d"), args[3]);
467 }
468 {
469 std::vector<const char*> args;
470 unsetenv("CEPH_ARGS");
471 args.push_back("a");
472 args.push_back("--");
473 args.push_back("c");
474 setenv("CEPH_ARGS", "d", 0);
475 clear_g_str_vec();
476 env_to_vec(args);
477 EXPECT_EQ(4u, args.size());
478 EXPECT_EQ(string("a"), args[0]);
479 EXPECT_EQ(string("d"), args[1]);
480 EXPECT_EQ(string("--"), args[2]);
481 EXPECT_EQ(string("c"), args[3]);
482 }
483 }
484 /*
485 * Local Variables:
486 * compile-command: "cd .. ; make unittest_ceph_argparse && ./unittest_ceph_argparse"
487 * End:
488 */