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