]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/ceph_argparse.cc
add subtree-ish sources for 12.0.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 env_to_vec(args);
377 EXPECT_EQ(0u, args.size());
378 env_to_vec(args, "WHATEVER");
379 EXPECT_EQ(0u, args.size());
380 args.push_back("a");
381 setenv("CEPH_ARGS", "b c", 0);
382 env_to_vec(args);
383 EXPECT_EQ(3u, args.size());
384 EXPECT_EQ(string("b"), args[1]);
385 EXPECT_EQ(string("c"), args[2]);
386 setenv("WHATEVER", "d e", 0);
387 env_to_vec(args, "WHATEVER");
388 EXPECT_EQ(5u, args.size());
389 EXPECT_EQ(string("d"), args[3]);
390 EXPECT_EQ(string("e"), args[4]);
391 }
392 {
393 std::vector<const char*> args;
394 unsetenv("CEPH_ARGS");
395 args.push_back("a");
396 args.push_back("--");
397 args.push_back("c");
398 setenv("CEPH_ARGS", "b -- d", 0);
399 env_to_vec(args);
400 EXPECT_EQ(5u, args.size());
401 EXPECT_EQ(string("a"), args[0]);
402 EXPECT_EQ(string("b"), args[1]);
403 EXPECT_EQ(string("--"), args[2]);
404 EXPECT_EQ(string("c"), args[3]);
405 EXPECT_EQ(string("d"), args[4]);
406 }
407 {
408 std::vector<const char*> args;
409 unsetenv("CEPH_ARGS");
410 args.push_back("a");
411 args.push_back("--");
412 setenv("CEPH_ARGS", "b -- c", 0);
413 env_to_vec(args);
414 EXPECT_EQ(4u, args.size());
415 EXPECT_EQ(string("a"), args[0]);
416 EXPECT_EQ(string("b"), args[1]);
417 EXPECT_EQ(string("--"), args[2]);
418 EXPECT_EQ(string("c"), args[3]);
419 }
420 {
421 std::vector<const char*> args;
422 unsetenv("CEPH_ARGS");
423 args.push_back("--");
424 args.push_back("c");
425 setenv("CEPH_ARGS", "b -- d", 0);
426 env_to_vec(args);
427 EXPECT_EQ(4u, args.size());
428 EXPECT_EQ(string("b"), args[0]);
429 EXPECT_EQ(string("--"), args[1]);
430 EXPECT_EQ(string("c"), args[2]);
431 EXPECT_EQ(string("d"), args[3]);
432 }
433 {
434 std::vector<const char*> args;
435 unsetenv("CEPH_ARGS");
436 args.push_back("b");
437 setenv("CEPH_ARGS", "c -- d", 0);
438 env_to_vec(args);
439 EXPECT_EQ(4u, args.size());
440 EXPECT_EQ(string("b"), args[0]);
441 EXPECT_EQ(string("c"), args[1]);
442 EXPECT_EQ(string("--"), args[2]);
443 EXPECT_EQ(string("d"), args[3]);
444 }
445 {
446 std::vector<const char*> args;
447 unsetenv("CEPH_ARGS");
448 args.push_back("a");
449 args.push_back("--");
450 args.push_back("c");
451 setenv("CEPH_ARGS", "-- d", 0);
452 env_to_vec(args);
453 EXPECT_EQ(4u, args.size());
454 EXPECT_EQ(string("a"), args[0]);
455 EXPECT_EQ(string("--"), args[1]);
456 EXPECT_EQ(string("c"), args[2]);
457 EXPECT_EQ(string("d"), args[3]);
458 }
459 {
460 std::vector<const char*> args;
461 unsetenv("CEPH_ARGS");
462 args.push_back("a");
463 args.push_back("--");
464 args.push_back("c");
465 setenv("CEPH_ARGS", "d", 0);
466 env_to_vec(args);
467 EXPECT_EQ(4u, args.size());
468 EXPECT_EQ(string("a"), args[0]);
469 EXPECT_EQ(string("d"), args[1]);
470 EXPECT_EQ(string("--"), args[2]);
471 EXPECT_EQ(string("c"), args[3]);
472 }
473 }
474 /*
475 * Local Variables:
476 * compile-command: "cd .. ; make unittest_ceph_argparse && ./unittest_ceph_argparse"
477 * End:
478 */