Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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  */