• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "utils/pandargs.h"
17 
18 #include <gtest/gtest.h>
19 
20 namespace ark::test {
21 
22 static constexpr const bool REF_DEF_BOOL = false;
23 static constexpr const int REF_DEF_INT = 0;
24 static constexpr const double REF_DEF_DOUBLE = 1.0;
25 static constexpr const uint32_t REF_DEF_UINT32 = 0;
26 static constexpr const uint64_t REF_DEF_UINT64 = 0;
27 
28 // NOLINTNEXTLINE(readability-magic-numbers)
29 static constexpr int ARGC_CONSISTENT = 21;
30 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
31 static constexpr const char *ARGV_CONSISTENT[] = {"gtest_app",
32                                                   "--bool",
33                                                   "on",
34                                                   "--int=42",
35                                                   "--string",
36                                                   "this is a string",
37                                                   "--double",
38                                                   ".42",
39                                                   "--uint32=4294967295",
40                                                   "--uint64=18446744073709551615",
41                                                   "--dlist=dlist1:dlist2:dlist3:dlist4",
42                                                   "--rint=42",
43                                                   "--ruint32=990000000",
44                                                   "--ruint64=99000000000",
45                                                   "tail1",
46                                                   "tail2 tail3",
47                                                   "tail4",
48                                                   "--",
49                                                   "rem1",
50                                                   "rem2",
51                                                   "rem3"};
52 
53 struct TestPandArgs {
54     PandArg<bool> *pab;
55     PandArg<int> *pai;
56     PandArg<double> *pad;
57     PandArg<std::string> *pas;
58     PandArg<uint32_t> *pau32;
59     PandArg<uint64_t> *pau64;
60     PandArg<arg_list_t> *pald;
61     PandArg<arg_list_t> *pal;
62     PandArg<int> *pair;
63     PandArg<uint32_t> *paur32;
64     PandArg<uint64_t> *paur64;
65 };
66 
67 struct TestTailPandArgs {
68     PandArg<bool> *tPab;
69     PandArg<int> *tPai;
70     PandArg<double> *tPad;
71     PandArg<std::string> *tPas;
72     PandArg<uint32_t> *tPau32;
73     PandArg<uint64_t> *tPau64;
74 };
75 
TestArgSet(PandArgParser & paParser,TestPandArgs & pandArgs)76 static void TestArgSet(PandArgParser &paParser, TestPandArgs &pandArgs)
77 {
78     // expect all arguments are set in parser
79     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pab));
80     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pab->GetName()));
81     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pai));
82     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pai->GetName()));
83     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pad));
84     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pad->GetName()));
85     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pas));
86     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pas->GetName()));
87     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pau32));
88     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pau32->GetName()));
89     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pau64));
90     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pau64->GetName()));
91     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pald));
92     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pald->GetName()));
93     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pal));
94     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pal->GetName()));
95     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pair));
96     EXPECT_TRUE(paParser.IsArgSet(pandArgs.pair->GetName()));
97     EXPECT_TRUE(paParser.IsArgSet(pandArgs.paur32));
98     EXPECT_TRUE(paParser.IsArgSet(pandArgs.paur32->GetName()));
99     EXPECT_TRUE(paParser.IsArgSet(pandArgs.paur64));
100     EXPECT_TRUE(paParser.IsArgSet(pandArgs.paur64->GetName()));
101 }
102 
TestTypeConsistency(TestPandArgs & pandArgs,const std::string & refDefStr)103 static void TestTypeConsistency(TestPandArgs &pandArgs, const std::string &refDefStr)
104 {
105     // expect default values and types are consistent
106     EXPECT_EQ(pandArgs.pab->GetDefaultValue(), REF_DEF_BOOL);
107     EXPECT_EQ(pandArgs.pab->GetDefaultValue(), pandArgs.pab->GetValue());
108     EXPECT_EQ(pandArgs.pab->GetType(), PandArgType::BOOL);
109 
110     EXPECT_EQ(pandArgs.pai->GetDefaultValue(), REF_DEF_INT);
111     EXPECT_EQ(pandArgs.pai->GetDefaultValue(), pandArgs.pai->GetValue());
112     EXPECT_EQ(pandArgs.pai->GetType(), PandArgType::INTEGER);
113 
114     EXPECT_DOUBLE_EQ(pandArgs.pad->GetValue(), REF_DEF_DOUBLE);
115     EXPECT_DOUBLE_EQ(pandArgs.pad->GetDefaultValue(), pandArgs.pad->GetValue());
116     EXPECT_EQ(pandArgs.pad->GetType(), PandArgType::DOUBLE);
117 
118     EXPECT_EQ(pandArgs.pas->GetDefaultValue(), refDefStr);
119     EXPECT_EQ(pandArgs.pas->GetDefaultValue(), pandArgs.pas->GetValue());
120     EXPECT_EQ(pandArgs.pas->GetType(), PandArgType::STRING);
121 
122     EXPECT_EQ(pandArgs.pau32->GetDefaultValue(), REF_DEF_UINT32);
123     EXPECT_EQ(pandArgs.pau32->GetDefaultValue(), pandArgs.pau32->GetValue());
124     EXPECT_EQ(pandArgs.pau32->GetType(), PandArgType::UINT32);
125 
126     EXPECT_EQ(pandArgs.pau64->GetDefaultValue(), REF_DEF_UINT64);
127     EXPECT_EQ(pandArgs.pau64->GetDefaultValue(), pandArgs.pau64->GetValue());
128     EXPECT_EQ(pandArgs.pau64->GetType(), PandArgType::UINT64);
129 
130     EXPECT_TRUE(pandArgs.pald->GetValue().empty());
131     EXPECT_EQ(pandArgs.pald->GetDefaultValue(), pandArgs.pald->GetValue());
132     EXPECT_EQ(pandArgs.pald->GetType(), PandArgType::LIST);
133 
134     EXPECT_TRUE(pandArgs.pal->GetValue().empty());
135     EXPECT_EQ(pandArgs.pal->GetDefaultValue(), pandArgs.pal->GetValue());
136     EXPECT_EQ(pandArgs.pal->GetType(), PandArgType::LIST);
137 
138     EXPECT_EQ(pandArgs.pair->GetDefaultValue(), REF_DEF_INT);
139     EXPECT_EQ(pandArgs.pair->GetDefaultValue(), pandArgs.pair->GetValue());
140     EXPECT_EQ(pandArgs.pair->GetType(), PandArgType::INTEGER);
141 
142     EXPECT_EQ(pandArgs.paur32->GetDefaultValue(), REF_DEF_UINT64);
143     EXPECT_EQ(pandArgs.paur32->GetDefaultValue(), pandArgs.paur32->GetValue());
144     EXPECT_EQ(pandArgs.paur32->GetType(), PandArgType::UINT32);
145 
146     EXPECT_EQ(pandArgs.paur64->GetDefaultValue(), REF_DEF_UINT64);
147     EXPECT_EQ(pandArgs.paur64->GetDefaultValue(), pandArgs.paur64->GetValue());
148     EXPECT_EQ(pandArgs.paur64->GetType(), PandArgType::UINT64);
149 }
150 
TestDublicate(PandArgParser & paParser)151 static void TestDublicate(PandArgParser &paParser)
152 {
153     // expect false on duplicate argument
154     PandArg<int> paiDup("int", 0U, "Integer number 0");
155     EXPECT_TRUE(paParser.IsArgSet(paiDup.GetName()));
156     EXPECT_FALSE(paParser.Add(&paiDup));
157 }
158 
TestTailFunctions(PandArgParser & paParser,TestTailPandArgs & tPandArgs)159 static void TestTailFunctions(PandArgParser &paParser, TestTailPandArgs &tPandArgs)
160 {
161     // add tail argument, expect false on duplicate
162     // erase tail, expect 0 tail size
163     EXPECT_EQ(paParser.GetTailSize(), 0U);
164     EXPECT_TRUE(paParser.PushBackTail(tPandArgs.tPai));
165     EXPECT_EQ(paParser.GetTailSize(), 1U);
166     EXPECT_FALSE(paParser.PushBackTail(tPandArgs.tPai));
167     paParser.PopBackTail();
168     EXPECT_EQ(paParser.GetTailSize(), 0U);
169 }
170 
TestHelpStringAndArgsList(PandArgParser & paParser,TestPandArgs & pandArgs)171 static void TestHelpStringAndArgsList(PandArgParser &paParser, TestPandArgs &pandArgs)
172 {
173     // expect help string formed right
174     {
175         std::string refString = "--" + pandArgs.pab->GetName() + ": " + pandArgs.pab->GetDesc() + "\n";
176         refString += "--" + pandArgs.pald->GetName() + ": " + pandArgs.pald->GetDesc() + "\n";
177         refString += "--" + pandArgs.pad->GetName() + ": " + pandArgs.pad->GetDesc() + "\n";
178         refString += "--" + pandArgs.pai->GetName() + ": " + pandArgs.pai->GetDesc() + "\n";
179         refString += "--" + pandArgs.pal->GetName() + ": " + pandArgs.pal->GetDesc() + "\n";
180         refString += "--" + pandArgs.pair->GetName() + ": " + pandArgs.pair->GetDesc() + "\n";
181         refString += "--" + pandArgs.paur32->GetName() + ": " + pandArgs.paur32->GetDesc() + "\n";
182         refString += "--" + pandArgs.paur64->GetName() + ": " + pandArgs.paur64->GetDesc() + "\n";
183         refString += "--" + pandArgs.pas->GetName() + ": " + pandArgs.pas->GetDesc() + "\n";
184         refString += "--" + pandArgs.pau32->GetName() + ": " + pandArgs.pau32->GetDesc() + "\n";
185         refString += "--" + pandArgs.pau64->GetName() + ": " + pandArgs.pau64->GetDesc() + "\n";
186         EXPECT_EQ(paParser.GetHelpString(), refString);
187     }
188 
189     // expect regular args list formed right
190     {
191         arg_list_t refArgDlist = pandArgs.pald->GetValue();
192         arg_list_t refArgList = pandArgs.pal->GetValue();
193         std::string refString =
194             "--" + pandArgs.pab->GetName() + "=" + std::to_string(static_cast<int>(pandArgs.pab->GetValue())) + "\n";
195         refString += "--" + pandArgs.pald->GetName() + "=";
196         for (const auto &i : refArgDlist) {
197             refString += i + ", ";
198         }
199         refString += "\n";
200         refString += "--" + pandArgs.pad->GetName() + "=" + std::to_string(pandArgs.pad->GetValue()) + "\n";
201         refString += "--" + pandArgs.pai->GetName() + "=" + std::to_string(pandArgs.pai->GetValue()) + "\n";
202         refString += "--" + pandArgs.pal->GetName() + "=";
203         for (const auto &i : refArgList) {
204             refString += i + ", ";
205         }
206         refString += "\n";
207         refString += "--" + pandArgs.pair->GetName() + "=" + std::to_string(pandArgs.pair->GetValue()) + "\n";
208         refString += "--" + pandArgs.paur32->GetName() + "=" + std::to_string(pandArgs.paur32->GetValue()) + "\n";
209         refString += "--" + pandArgs.paur64->GetName() + "=" + std::to_string(pandArgs.paur64->GetValue()) + "\n";
210         refString += "--" + pandArgs.pas->GetName() + "=" + pandArgs.pas->GetValue() + "\n";
211         refString += "--" + pandArgs.pau32->GetName() + "=" + std::to_string(pandArgs.pau32->GetValue()) + "\n";
212         refString += "--" + pandArgs.pau64->GetName() + "=" + std::to_string(pandArgs.pau64->GetValue()) + "\n";
213         EXPECT_EQ(paParser.GetRegularArgs(), refString);
214     }
215 }
216 
217 // NOLINTBEGIN(modernize-avoid-c-arrays)
TestBoolean(PandArgParser & paParser,TestPandArgs & pandArgs)218 static void TestBoolean(PandArgParser &paParser, TestPandArgs &pandArgs)
219 {
220     // expect all boolean values processed right
221     {
222         static const char *trueValues[] = {"true", "on", "1"};
223         static const char *falseValues[] = {"false", "off", "0"};
224         static constexpr const int ARGC_BOOL_ONLY = 3;
225         static const char *argvBoolOnly[ARGC_BOOL_ONLY];
226         argvBoolOnly[0U] = "gtest_app";
227         std::string s = "--" + pandArgs.pab->GetName();
228         argvBoolOnly[1U] = s.c_str();
229 
230         // NOLINTNEXTLINE(modernize-loop-convert)
231         for (size_t i = 0; i < 3U; i++) {
232             argvBoolOnly[2U] = trueValues[i];
233             EXPECT_TRUE(paParser.Parse(ARGC_BOOL_ONLY, argvBoolOnly));
234             EXPECT_TRUE(pandArgs.pab->GetValue());
235         }
236         // NOLINTNEXTLINE(modernize-loop-convert)
237         for (size_t i = 0; i < 3U; i++) {
238             argvBoolOnly[2U] = falseValues[i];
239             EXPECT_TRUE(paParser.Parse(ARGC_BOOL_ONLY, argvBoolOnly));
240             EXPECT_FALSE(pandArgs.pab->GetValue());
241         }
242     }
243 
244     // expect wrong boolean arguments with "=" processed right
245     {
246         static const int ARGC_BOOL_ONLY = 2;
247         static const char *argvBoolOnly[ARGC_BOOL_ONLY];
248         argvBoolOnly[0U] = "gtest_app";
249         std::string s = "--" + pandArgs.pab->GetName() + "=";
250         argvBoolOnly[1U] = s.c_str();
251         EXPECT_FALSE(paParser.Parse(ARGC_BOOL_ONLY, argvBoolOnly));
252     }
253 
254     // expect boolean at the end of arguments line is true
255     {
256         static const int ARGC_BOOL_ONLY = 2;
257         static const char *argvBoolOnly[ARGC_BOOL_ONLY];
258         argvBoolOnly[0U] = "gtest_app";
259         std::string s = "--" + pandArgs.pab->GetName();
260         argvBoolOnly[1U] = s.c_str();
261         EXPECT_TRUE(paParser.Parse(ARGC_BOOL_ONLY, argvBoolOnly));
262         EXPECT_TRUE(pandArgs.pab->GetValue());
263     }
264 }
265 
TestSignedValues(PandArgParser & paParser,TestPandArgs & pandArgs)266 static void TestSignedValues(PandArgParser &paParser, TestPandArgs &pandArgs)
267 {
268     // expect positive and negative integer values processed right
269     {
270         static constexpr const int REF_INT_POS = 42422424;
271         static constexpr const int REF_INT_NEG = -42422424;
272         static constexpr const int ARGC_INT_ONLY = 3;
273         static const char *argvIntOnly[ARGC_INT_ONLY];
274         argvIntOnly[0U] = "gtest_app";
275         std::string s = "--" + pandArgs.pai->GetName();
276         argvIntOnly[1U] = s.c_str();
277         argvIntOnly[2U] = "42422424";
278         EXPECT_TRUE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
279         EXPECT_EQ(pandArgs.pai->GetValue(), REF_INT_POS);
280         argvIntOnly[2U] = "-42422424";
281         EXPECT_TRUE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
282         EXPECT_EQ(pandArgs.pai->GetValue(), REF_INT_NEG);
283     }
284 
285     // expect positive and negative double values processed right
286     {
287         static constexpr const double REF_DOUBLE_POS = 4242.2424;
288         static constexpr const double REF_DOUBLE_NEG = -4242.2424;
289         static constexpr const int ARGC_DOUBLE_ONLY = 3;
290         static const char *argvDoubleOnly[ARGC_DOUBLE_ONLY];
291         argvDoubleOnly[0U] = "gtest_app";
292         std::string s = "--" + pandArgs.pad->GetName();
293         argvDoubleOnly[1U] = s.c_str();
294         argvDoubleOnly[2U] = "4242.2424";
295         EXPECT_TRUE(paParser.Parse(ARGC_DOUBLE_ONLY, argvDoubleOnly));
296         EXPECT_EQ(pandArgs.pad->GetValue(), REF_DOUBLE_POS);
297         argvDoubleOnly[2U] = "-4242.2424";
298         EXPECT_TRUE(paParser.Parse(ARGC_DOUBLE_ONLY, argvDoubleOnly));
299         EXPECT_EQ(pandArgs.pad->GetValue(), REF_DOUBLE_NEG);
300     }
301 }
302 
TestIntValues(PandArgParser & paParser,TestPandArgs & pandArgs)303 static void TestIntValues(PandArgParser &paParser, TestPandArgs &pandArgs)
304 {
305     // expect uint32_t values processed right
306     {
307         static constexpr const uint32_t REF_UINT32_POS = 4242422424;
308         static constexpr const int ARGC_UINT32_ONLY = 3;
309         static const char *argvUint32Only[ARGC_UINT32_ONLY];
310         argvUint32Only[0U] = "gtest_app";
311         std::string s = "--" + pandArgs.pau32->GetName();
312         argvUint32Only[1U] = s.c_str();
313         argvUint32Only[2U] = "4242422424";
314         EXPECT_TRUE(paParser.Parse(ARGC_UINT32_ONLY, argvUint32Only));
315         EXPECT_EQ(pandArgs.pau32->GetValue(), REF_UINT32_POS);
316     }
317 
318     // expect uint64_t values processed right
319     {
320         static constexpr const uint64_t REF_UINT64_POS = 424242422424;
321         static constexpr const int ARGC_UINT64_ONLY = 3;
322         static const char *argvUint64Only[ARGC_UINT64_ONLY];
323         argvUint64Only[0U] = "gtest_app";
324         std::string s = "--" + pandArgs.pau64->GetName();
325         argvUint64Only[1U] = s.c_str();
326         argvUint64Only[2U] = "424242422424";
327         EXPECT_TRUE(paParser.Parse(ARGC_UINT64_ONLY, argvUint64Only));
328         EXPECT_EQ(pandArgs.pau64->GetValue(), REF_UINT64_POS);
329     }
330 }
331 
TestOutOfRangeInt(PandArgParser & paParser,TestPandArgs & pandArgs)332 static void TestOutOfRangeInt(PandArgParser &paParser, TestPandArgs &pandArgs)
333 {
334     // expect out of range uint32_t values processed right
335     {
336         static constexpr const int ARGC_UINT32_ONLY = 3;
337         static const char *argvUint32Only[ARGC_UINT32_ONLY];
338         argvUint32Only[0U] = "gtest_app";
339         std::string s = "--" + pandArgs.pau32->GetName();
340         argvUint32Only[1U] = s.c_str();
341         argvUint32Only[2U] = "424224244242242442422424";
342         EXPECT_FALSE(paParser.Parse(ARGC_UINT32_ONLY, argvUint32Only));
343         argvUint32Only[2U] = "0xffffffffffffffffffffffffff";
344         EXPECT_FALSE(paParser.Parse(ARGC_UINT32_ONLY, argvUint32Only));
345     }
346 
347     // expect out of range uint64_t values processed right
348     {
349         static const int ARGC_UINT64_ONLY = 3;
350         static const char *argvUint64Only[ARGC_UINT64_ONLY];
351         argvUint64Only[0U] = "gtest_app";
352         std::string s = "--" + pandArgs.pau64->GetName();
353         argvUint64Only[1U] = s.c_str();
354         argvUint64Only[2U] = "424224244242242442422424";
355         EXPECT_FALSE(paParser.Parse(ARGC_UINT64_ONLY, argvUint64Only));
356         argvUint64Only[2U] = "0xffffffffffffffffffffffffff";
357         EXPECT_FALSE(paParser.Parse(ARGC_UINT64_ONLY, argvUint64Only));
358     }
359 }
360 
TestStringArg(PandArgParser & paParser,TestPandArgs & pandArgs)361 static void TestStringArg(PandArgParser &paParser, TestPandArgs &pandArgs)
362 {
363     // expect string argument of one word and multiple word processed right
364     {
365         static const std::string REF_ONE_STRING = "string";
366         static const std::string REF_MULTIPLE_STRING = "this is a string";
367         static const char *strArgname = "--string";
368         static constexpr const int ARGC_ONE_STRING = 3;
369         static const char *argvOneString[ARGC_ONE_STRING] = {"gtest_app", strArgname, "string"};
370         static constexpr const int ARGC_MULTIPLE_STRING = 3;
371         static const char *argvMultipleString[ARGC_MULTIPLE_STRING] = {"gtest_app", strArgname, "this is a string"};
372         EXPECT_TRUE(paParser.Parse(ARGC_MULTIPLE_STRING, argvMultipleString));
373         EXPECT_EQ(pandArgs.pas->GetValue(), REF_MULTIPLE_STRING);
374         EXPECT_TRUE(paParser.Parse(ARGC_ONE_STRING, argvOneString));
375         EXPECT_EQ(pandArgs.pas->GetValue(), REF_ONE_STRING);
376     }
377 
378     // expect string at the end of line is an empty string
379     {
380         static constexpr const int ARGC_STRING_ONLY = 2;
381         static const char *argvStringOnly[ARGC_STRING_ONLY];
382         argvStringOnly[0U] = "gtest_app";
383         std::string s = "--" + pandArgs.pas->GetName();
384         argvStringOnly[1U] = s.c_str();
385         EXPECT_TRUE(paParser.Parse(ARGC_STRING_ONLY, argvStringOnly));
386         EXPECT_EQ(pandArgs.pas->GetValue(), "");
387     }
388 }
389 
TestListArg(PandArgParser & paParser,TestPandArgs & pandArgs)390 static void TestListArg(PandArgParser &paParser, TestPandArgs &pandArgs)
391 {
392     // expect list argument processed right
393     {
394         pandArgs.pald->ResetDefaultValue();
395         static const arg_list_t REF_LIST = {"list1", "list2", "list3"};
396         std::string s = "--" + pandArgs.pald->GetName();
397         static const char *listArgname = s.c_str();
398         static constexpr const int ARGC_LIST_ONLY = 7;
399         static const char *argvListOnly[ARGC_LIST_ONLY] = {"gtest_app", listArgname, "list1", listArgname,
400                                                            "list2",     listArgname, "list3"};
401         EXPECT_TRUE(paParser.Parse(ARGC_LIST_ONLY, argvListOnly));
402         ASSERT_EQ(pandArgs.pald->GetValue().size(), REF_LIST.size());
403         for (std::size_t i = 0; i < REF_LIST.size(); ++i) {
404             EXPECT_EQ(pandArgs.pald->GetValue()[i], REF_LIST[i]);
405         }
406     }
407 
408     // expect list argument without delimiter processed right
409     {
410         pandArgs.pal->ResetDefaultValue();
411         static const arg_list_t REF_LIST = {"list1", "list2", "list3", "list4"};
412         std::string s = "--" + pandArgs.pal->GetName();
413         static const char *listArgname = s.c_str();
414         static constexpr const int ARGC_LIST_ONLY = 9;
415         static const char *argvListOnly[ARGC_LIST_ONLY] = {"gtest_app", listArgname, "list1",     listArgname, "list2",
416                                                            listArgname, "list3",     listArgname, "list4"};
417         EXPECT_TRUE(paParser.Parse(ARGC_LIST_ONLY, argvListOnly));
418         ASSERT_EQ(pandArgs.pal->GetValue().size(), REF_LIST.size());
419         for (std::size_t i = 0; i < REF_LIST.size(); ++i) {
420             EXPECT_EQ(pandArgs.pal->GetValue()[i], REF_LIST[i]);
421         }
422     }
423 }
424 
TestDelimiterListArg(PandArgParser & paParser,TestPandArgs & pandArgs)425 static void TestDelimiterListArg(PandArgParser &paParser, TestPandArgs &pandArgs)
426 {
427     // expect delimiter list argument processed right
428     {
429         pandArgs.pald->ResetDefaultValue();
430         static const arg_list_t REF_DLIST = {"dlist1", "dlist2", "dlist3"};
431         std::string s = "--" + pandArgs.pald->GetName();
432         static const char *listArgname = s.c_str();
433         static constexpr const int ARGC_DLIST_ONLY = 3;
434         static const char *argvDlistOnly[ARGC_DLIST_ONLY] = {"gtest_app", listArgname, "dlist1:dlist2:dlist3"};
435         EXPECT_TRUE(paParser.Parse(ARGC_DLIST_ONLY, argvDlistOnly));
436         ASSERT_EQ(pandArgs.pald->GetValue().size(), REF_DLIST.size());
437         for (std::size_t i = 0; i < REF_DLIST.size(); ++i) {
438             EXPECT_EQ(pandArgs.pald->GetValue()[i], REF_DLIST[i]);
439         }
440     }
441 
442     // expect delimiter and multiple list argument processed right
443     {
444         pandArgs.pald->ResetDefaultValue();
445         static const arg_list_t REF_LIST = {"dlist1", "dlist2", "list1", "list2", "dlist3", "dlist4"};
446         std::string s = "--" + pandArgs.pald->GetName();
447         static const char *listArgname = s.c_str();
448         static constexpr const int ARGC_LIST = 9;
449         static const char *argvList[ARGC_LIST] = {"gtest_app", listArgname, "dlist1:dlist2", listArgname,    "list1",
450                                                   listArgname, "list2",     listArgname,     "dlist3:dlist4"};
451         EXPECT_TRUE(paParser.Parse(ARGC_LIST, argvList));
452         ASSERT_EQ(pandArgs.pald->GetValue().size(), REF_LIST.size());
453         for (std::size_t i = 0; i < REF_LIST.size(); ++i) {
454             EXPECT_EQ(pandArgs.pald->GetValue()[i], REF_LIST[i]);
455         }
456     }
457 }
458 
TestSignedIntWihRange(PandArgParser & paParser,TestPandArgs & pandArgs)459 static void TestSignedIntWihRange(PandArgParser &paParser, TestPandArgs &pandArgs)
460 {
461     // expect positive and negative integer values with range processed right
462     {
463         static constexpr const int REF_INT_POS = 99;
464         static constexpr const int REF_INT_NEG = -99;
465         static constexpr const int ARGC_INT_ONLY = 3;
466         static const char *argvIntOnly[ARGC_INT_ONLY];
467         argvIntOnly[0U] = "gtest_app";
468         std::string s = "--" + pandArgs.pair->GetName();
469         argvIntOnly[1U] = s.c_str();
470         argvIntOnly[2U] = "99";
471         EXPECT_TRUE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
472         EXPECT_EQ(pandArgs.pair->GetValue(), REF_INT_POS);
473         argvIntOnly[2U] = "-99";
474         EXPECT_TRUE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
475         EXPECT_EQ(pandArgs.pair->GetValue(), REF_INT_NEG);
476     }
477 
478     // expect wrong positive and negative integer values with range processed right
479     {
480         static constexpr const int REF_INT_POS = 101;
481         static constexpr const int REF_INT_NEG = -101;
482         static constexpr const int ARGC_INT_ONLY = 3;
483         static const char *argvIntOnly[ARGC_INT_ONLY];
484         argvIntOnly[0U] = "gtest_app";
485         std::string s = "--" + pandArgs.pair->GetName();
486         argvIntOnly[1U] = s.c_str();
487         argvIntOnly[2U] = "101";
488         EXPECT_FALSE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
489         argvIntOnly[2U] = "-101";
490         EXPECT_FALSE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
491     }
492 }
493 
TestUInt32WihRange(PandArgParser & paParser,TestPandArgs & pandArgs)494 static void TestUInt32WihRange(PandArgParser &paParser, TestPandArgs &pandArgs)
495 {
496     // expect uint32_t values with range processed right
497     {
498         static constexpr const uint32_t REF_INT_MIN = 1;
499         static constexpr const uint32_t REF_INT_MAX = 990000000;
500         static constexpr const int ARGC_INT_ONLY = 3;
501         static const char *argvIntOnly[ARGC_INT_ONLY];
502         argvIntOnly[0U] = "gtest_app";
503         std::string s = "--" + pandArgs.paur32->GetName();
504         argvIntOnly[1U] = s.c_str();
505         argvIntOnly[2U] = "1";
506         EXPECT_TRUE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
507         EXPECT_EQ(pandArgs.paur32->GetValue(), REF_INT_MIN);
508         argvIntOnly[2U] = "990000000";
509         EXPECT_TRUE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
510         EXPECT_EQ(pandArgs.paur32->GetValue(), REF_INT_MAX);
511     }
512 
513     // expect wrong uint32_t values with range processed right
514     {
515         static constexpr const uint32_t REF_INT_MIN = -1;
516         static constexpr const uint32_t REF_INT_MAX = 1000000001;
517         static constexpr const int ARGC_INT_ONLY = 3;
518         static const char *argvIntOnly[ARGC_INT_ONLY];
519         argvIntOnly[0U] = "gtest_app";
520         std::string s = "--" + pandArgs.paur32->GetName();
521         argvIntOnly[1U] = s.c_str();
522         argvIntOnly[2U] = "-1";
523         EXPECT_FALSE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
524         argvIntOnly[2U] = "1000000001";
525         EXPECT_FALSE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
526     }
527 }
528 
TestEmptyString(PandArgParser & paParser,TestPandArgs & pandArgs)529 static void TestEmptyString(PandArgParser &paParser, TestPandArgs &pandArgs)
530 {
531     // expect list at the end of line is a list with empty string
532     pandArgs.pald->ResetDefaultValue();
533     static const arg_list_t REF_LIST = {""};
534     static constexpr const int ARGC_LIST_ONLY = 2;
535     static const char *argvListOnly[ARGC_LIST_ONLY];
536     argvListOnly[0U] = "gtest_app";
537     std::string s = "--" + pandArgs.pald->GetName();
538     argvListOnly[1U] = s.c_str();
539     EXPECT_TRUE(paParser.Parse(ARGC_LIST_ONLY, argvListOnly));
540     EXPECT_EQ(pandArgs.pald->GetValue(), REF_LIST);
541 }
542 
TestTailConsistency(PandArgParser & paParser,TestTailPandArgs & tPandArgs)543 static void TestTailConsistency(PandArgParser &paParser, TestTailPandArgs &tPandArgs)
544 {
545     // expect true on IsTailEnabled when tail is enabled, false otherwise
546     {
547         paParser.EnableTail();
548         EXPECT_TRUE(paParser.IsTailEnabled());
549         paParser.DisableTail();
550         EXPECT_FALSE(paParser.IsTailEnabled());
551     }
552 
553     // expect tail only argument is consistent
554     {
555         static constexpr const int ARGC_TAIL_ONLY = 2;
556         static const char *argvTailOnly[] = {"gtest_app", "tail1"};
557         static const std::string REF_STR_TAIL = "tail1";
558         paParser.EnableTail();
559         paParser.PushBackTail(tPandArgs.tPas);
560         EXPECT_TRUE(paParser.Parse(ARGC_TAIL_ONLY, argvTailOnly));
561         ASSERT_EQ(tPandArgs.tPas->GetValue(), REF_STR_TAIL);
562         paParser.DisableTail();
563         paParser.EraseTail();
564     }
565 
566     // expect multiple tail only argument is consistent
567     {
568         static constexpr const int ARGC_TAIL_ONLY = 7;
569         static const char *argvTailOnly[] = {"gtest_app", "str_tail", "off", "-4", "3.14", "2", "4"};
570         static const std::string STR_REF = "str_tail";
571         static constexpr const bool BOOL_REF = false;
572         static constexpr const int INT_REF = -4;
573         static constexpr const double DOUBLE_REF = 3.14;
574         static constexpr const uint32_t UINT32_REF = 2;
575         static constexpr const uint64_t UINT64_REF = 4;
576         paParser.EnableTail();
577         paParser.PushBackTail(tPandArgs.tPas);
578         paParser.PushBackTail(tPandArgs.tPab);
579         paParser.PushBackTail(tPandArgs.tPai);
580         paParser.PushBackTail(tPandArgs.tPad);
581         paParser.PushBackTail(tPandArgs.tPau32);
582         paParser.PushBackTail(tPandArgs.tPau64);
583         EXPECT_EQ(paParser.GetTailSize(), 6U);
584         EXPECT_TRUE(paParser.Parse(ARGC_TAIL_ONLY, argvTailOnly));
585         EXPECT_EQ(tPandArgs.tPas->GetValue(), STR_REF);
586         EXPECT_EQ(tPandArgs.tPab->GetValue(), BOOL_REF);
587         EXPECT_EQ(tPandArgs.tPai->GetValue(), INT_REF);
588         EXPECT_DOUBLE_EQ(tPandArgs.tPad->GetValue(), DOUBLE_REF);
589         EXPECT_EQ(tPandArgs.tPau32->GetValue(), UINT32_REF);
590         EXPECT_EQ(tPandArgs.tPau64->GetValue(), UINT64_REF);
591         paParser.DisableTail();
592         paParser.EraseTail();
593         EXPECT_EQ(paParser.GetTailSize(), 0U);
594     }
595 }
TestUInt64WihRange(PandArgParser & paParser,TestPandArgs & pandArgs)596 static void TestUInt64WihRange(PandArgParser &paParser, TestPandArgs &pandArgs)
597 {
598     // expect uint64_t values with range processed right
599     {
600         static const uint64_t REF_INT_MIN = 1;
601         static const uint64_t REF_INT_MAX = 99000000000;
602         static const int ARGC_INT_ONLY = 3;
603         static const char *argvIntOnly[ARGC_INT_ONLY];
604         argvIntOnly[0U] = "gtest_app";
605         std::string s = "--" + pandArgs.paur64->GetName();
606         argvIntOnly[1U] = s.c_str();
607         argvIntOnly[2U] = "1";
608         EXPECT_TRUE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
609         EXPECT_EQ(pandArgs.paur64->GetValue(), REF_INT_MIN);
610         argvIntOnly[2U] = "99000000000";
611         EXPECT_TRUE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
612         EXPECT_EQ(pandArgs.paur64->GetValue(), REF_INT_MAX);
613     }
614 
615     // expect wrong uint64_t values with range processed right
616     {
617         static constexpr const uint64_t REF_INT_MIN = -1;
618         static constexpr const uint64_t REF_INT_MAX = 100000000001;
619         static constexpr const int ARGC_INT_ONLY = 3;
620         static const char *argvIntOnly[ARGC_INT_ONLY];
621         argvIntOnly[0U] = "gtest_app";
622         std::string s = "--" + pandArgs.paur64->GetName();
623         argvIntOnly[1U] = s.c_str();
624         argvIntOnly[2U] = "-1";
625         EXPECT_FALSE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
626         argvIntOnly[2U] = "100000000001";
627         EXPECT_FALSE(paParser.Parse(ARGC_INT_ONLY, argvIntOnly));
628     }
629 }
630 
TestWrongTailArg(PandArgParser & paParser,TestTailPandArgs & tPandArgs)631 static void TestWrongTailArg(PandArgParser &paParser, TestTailPandArgs &tPandArgs)
632 {
633     // expect parse fail on wrong tail argument type
634     paParser.EnableTail();
635     static constexpr const int ARGC_TAIL_ONLY = 3;
636     // boolean value instead of integer
637     static const char *argvTailOnly[] = {"gtest_app", "str_tail", "off"};
638     static const std::string STR_REF = "str_tail";
639     paParser.PushBackTail(tPandArgs.tPas);
640     paParser.PushBackTail(tPandArgs.tPai);
641     EXPECT_EQ(paParser.GetTailSize(), 2U);
642     EXPECT_FALSE(paParser.Parse(ARGC_TAIL_ONLY, argvTailOnly));
643     EXPECT_EQ(tPandArgs.tPas->GetValue(), STR_REF);
644     paParser.DisableTail();
645     paParser.EraseTail();
646     EXPECT_EQ(paParser.GetTailSize(), 0U);
647 }
648 
TestTailAfterString(PandArgParser & paParser,TestPandArgs & pandArgs,TestTailPandArgs & tPandArgs)649 static void TestTailAfterString(PandArgParser &paParser, TestPandArgs &pandArgs, TestTailPandArgs &tPandArgs)
650 {
651     // expect right tail argument processing after preceiding string argument
652     paParser.EnableTail();
653     static const char *strArgname = "--string";
654     static const std::string REF_STRING = "this is a reference string";
655     static const std::string REF_T_STR = "string";
656     static constexpr const double REF_T_DOUBLE = 0.1;
657     static constexpr const bool REF_T_BOOL = true;
658     static constexpr const uint32_t REF_T_UINT32 = 32;
659     static constexpr const uint64_t REF_T_UINT64 = 64;
660     static constexpr const int ARGC_TAIL_STRING = 8;
661     static const char *argvTailString[] = {"gtest_app", strArgname, "this is a reference string", "string", ".1", "on",
662                                            "32",        "64"};
663     paParser.PushBackTail(tPandArgs.tPas);
664     paParser.PushBackTail(tPandArgs.tPad);
665     paParser.PushBackTail(tPandArgs.tPab);
666     paParser.PushBackTail(tPandArgs.tPau32);
667     paParser.PushBackTail(tPandArgs.tPau64);
668     EXPECT_TRUE(paParser.Parse(ARGC_TAIL_STRING, argvTailString));
669     EXPECT_EQ(pandArgs.pas->GetValue(), REF_STRING);
670     EXPECT_EQ(tPandArgs.tPas->GetValue(), REF_T_STR);
671     EXPECT_EQ(tPandArgs.tPad->GetValue(), REF_T_DOUBLE);
672     EXPECT_EQ(tPandArgs.tPab->GetValue(), REF_T_BOOL);
673     EXPECT_EQ(tPandArgs.tPau32->GetValue(), REF_T_UINT32);
674     EXPECT_EQ(tPandArgs.tPau64->GetValue(), REF_T_UINT64);
675     paParser.DisableTail();
676     paParser.EraseTail();
677 }
678 
TestTailAfterList(PandArgParser & paParser,TestPandArgs & pandArgs,TestTailPandArgs & tPandArgs)679 static void TestTailAfterList(PandArgParser &paParser, TestPandArgs &pandArgs, TestTailPandArgs &tPandArgs)
680 {
681     // expect right tail argument processing after preceiding list argument
682     pandArgs.pald->ResetDefaultValue();
683     paParser.EnableTail();
684     static const char *listArgname = "--dlist";
685     static const arg_list_t REF_LIST = {"list1", "list2", "list3", "list4", "list5"};
686     static constexpr const double REF_T_DOUBLE = -7;
687     static constexpr const bool REF_T_BOOL = true;
688     static constexpr const int REF_T_INT = 255;
689     static constexpr const uint32_t REF_T_UINT32 = 32;
690     static constexpr const uint64_t REF_T_UINT64 = 64;
691     static constexpr const int ARGC_TAIL_LIST = 16;
692     static const char *argvTailList[] = {"gtest_app", listArgname, "list1", listArgname, "list2", listArgname,
693                                          "list3",     listArgname, "list4", listArgname, "list5", "true",
694                                          "255",       "-7",        "32",    "64"};
695     paParser.PushBackTail(tPandArgs.tPab);
696     paParser.PushBackTail(tPandArgs.tPai);
697     paParser.PushBackTail(tPandArgs.tPad);
698     paParser.PushBackTail(tPandArgs.tPau32);
699     paParser.PushBackTail(tPandArgs.tPau64);
700     EXPECT_TRUE(paParser.Parse(ARGC_TAIL_LIST, argvTailList));
701     ASSERT_EQ(pandArgs.pald->GetValue().size(), REF_LIST.size());
702     for (std::size_t i = 0; i < REF_LIST.size(); i++) {
703         EXPECT_EQ(pandArgs.pald->GetValue()[i], REF_LIST[i]);
704     }
705     EXPECT_EQ(tPandArgs.tPab->GetValue(), REF_T_BOOL);
706     EXPECT_EQ(tPandArgs.tPai->GetValue(), REF_T_INT);
707     EXPECT_DOUBLE_EQ(tPandArgs.tPad->GetValue(), REF_T_DOUBLE);
708     EXPECT_EQ(tPandArgs.tPau32->GetValue(), REF_T_UINT32);
709     EXPECT_EQ(tPandArgs.tPau64->GetValue(), REF_T_UINT64);
710 
711     paParser.DisableTail();
712     paParser.EraseTail();
713 }
714 
TestTailAfterNoparamBoolean(PandArgParser & paParser,TestPandArgs & pandArgs,TestTailPandArgs & tPandArgs,const std::string & refDefStr)715 static void TestTailAfterNoparamBoolean(PandArgParser &paParser, TestPandArgs &pandArgs, TestTailPandArgs &tPandArgs,
716                                         const std::string &refDefStr)
717 {
718     // expect right tail argument processing after noparam boolean argument
719     paParser.EnableTail();
720     PandArg<std::string> tPas0("tail_string0", refDefStr, "Sample tail string argument 0");
721     PandArg<std::string> tPas1("tail_string1", refDefStr, "Sample tail string argument 1");
722     static const std::string REF_T_STR1 = "offtail1";
723     static const std::string REF_T_STR2 = "offtail2";
724     static const std::string REF_T_STR3 = "offtail3";
725     static constexpr const int ARGC_TAIL_BOOL = 5;
726     static const char *argvTailBool[] = {"gtest_app", "--bool", "offtail1", "offtail2", "offtail3"};
727     paParser.PushBackTail(tPandArgs.tPas);
728     paParser.PushBackTail(&tPas0);
729     paParser.PushBackTail(&tPas1);
730     EXPECT_TRUE(paParser.Parse(ARGC_TAIL_BOOL, argvTailBool));
731     EXPECT_TRUE(pandArgs.pab->GetValue());
732     EXPECT_EQ(tPandArgs.tPas->GetValue(), REF_T_STR1);
733     EXPECT_EQ(tPas0.GetValue(), REF_T_STR2);
734     EXPECT_EQ(tPas1.GetValue(), REF_T_STR3);
735     paParser.DisableTail();
736     paParser.EraseTail();
737 }
738 
TestTailExceedsArgsNum(PandArgParser & paParser,TestTailPandArgs & tPandArgs,const std::string & refDefStr)739 static void TestTailExceedsArgsNum(PandArgParser &paParser, TestTailPandArgs &tPandArgs, const std::string &refDefStr)
740 {
741     // expect fail on amount of tail arguments more then pa_parser may have
742     paParser.EnableTail();
743     static const int ARGC_TAIL = 5;
744     static const char *argvTail[] = {"gtest_app", "gdb", "--args", "file.bin", "entry"};
745 
746     PandArg<std::string> tPas1("tail_string1", refDefStr, "Sample tail string argument 1");
747     paParser.PushBackTail(tPandArgs.tPas);
748     paParser.PushBackTail(&tPas1);
749 
750     EXPECT_EQ(paParser.GetTailSize(), 2U);
751     EXPECT_FALSE(paParser.Parse(ARGC_TAIL, argvTail));
752     paParser.DisableTail();
753     paParser.EraseTail();
754 }
755 
TestTailRemainder(PandArgParser & paParser,TestPandArgs & pandArgs)756 static void TestTailRemainder(PandArgParser &paParser, TestPandArgs &pandArgs)
757 {
758     // expect remainder arguments only parsed as expected
759     {
760         paParser.EnableRemainder();
761         static const arg_list_t REF_REM = {"rem1", "rem2", "rem3"};
762         static int argcRem = 5;
763         static const char *argvRem[] = {"gtest_app", "--", "rem1", "rem2", "rem3"};
764         paParser.Parse(argcRem, argvRem);
765         arg_list_t remainder = paParser.GetRemainder();
766         EXPECT_EQ(remainder.size(), REF_REM.size());
767         for (std::size_t i = 0; i < remainder.size(); i++) {
768             EXPECT_EQ(remainder[i], REF_REM[i]);
769         }
770         paParser.DisableRemainder();
771     }
772 
773     // expect regular argument before remainder parsed right
774     {
775         paParser.EnableRemainder();
776         static const arg_list_t REF_REM = {"rem1", "rem2", "rem3"};
777         std::string boolName = "--" + pandArgs.pab->GetName();
778         static int argcRem = 6;
779         static const char *argvRem[] = {"gtest_app", boolName.c_str(), "--", "rem1", "rem2", "rem3"};
780         paParser.Parse(argcRem, argvRem);
781         EXPECT_TRUE(pandArgs.pab->GetValue());
782         arg_list_t remainder = paParser.GetRemainder();
783         EXPECT_EQ(remainder.size(), REF_REM.size());
784         for (std::size_t i = 0; i < remainder.size(); i++) {
785             EXPECT_EQ(remainder[i], REF_REM[i]);
786         }
787         paParser.DisableRemainder();
788     }
789 }
790 
TestAllArgs(PandArgParser & paParser,TestPandArgs & pandArgs,TestTailPandArgs & tPandArgs,const std::string & refDefStr)791 static void TestAllArgs(PandArgParser &paParser, TestPandArgs &pandArgs, TestTailPandArgs &tPandArgs,
792                         const std::string &refDefStr)
793 {
794     // expect that all arguments parsed as expected
795     pandArgs.pald->ResetDefaultValue();
796     paParser.EnableTail();
797     paParser.EnableRemainder();
798     static const arg_list_t REF_REM = {"rem1", "rem2", "rem3"};
799     PandArg<std::string> tPas0("tail_string0", refDefStr, "Sample tail string argument 0");
800     PandArg<std::string> tPas1("tail_string1", refDefStr, "Sample tail string argument 1");
801     static constexpr const bool REF_BOOL = true;
802     static constexpr const int REF_INT = 42;
803     static const arg_list_t REF_DLIST = {"dlist1", "dlist2", "dlist3", "dlist4"};
804     static const std::string REF_T_STR1 = "tail1";
805     static const std::string REF_T_STR2 = "tail2 tail3";
806     static const std::string REF_T_STR3 = "tail4";
807     static const std::string REF_STR = "this is a string";
808     static constexpr const double REF_DBL = 0.42;
809     static constexpr const uint32_t REF_UINT32 = std::numeric_limits<std::uint32_t>::max();
810     static constexpr const uint32_t REF_UINT32R = 990000000;
811     static constexpr const uint64_t REF_UINT64 = std::numeric_limits<std::uint64_t>::max();
812     static constexpr const uint64_t REF_UINT64R = 99000000000;
813 
814     paParser.PushBackTail(tPandArgs.tPas);
815     paParser.PushBackTail(&tPas0);
816     paParser.PushBackTail(&tPas1);
817     EXPECT_TRUE(paParser.Parse(ARGC_CONSISTENT, ARGV_CONSISTENT));
818     EXPECT_EQ(pandArgs.pab->GetValue(), REF_BOOL);
819     EXPECT_EQ(pandArgs.pai->GetValue(), REF_INT);
820     EXPECT_EQ(pandArgs.pas->GetValue(), REF_STR);
821     EXPECT_DOUBLE_EQ(pandArgs.pad->GetValue(), REF_DBL);
822     EXPECT_EQ(pandArgs.pau32->GetValue(), REF_UINT32);
823     EXPECT_EQ(pandArgs.pau64->GetValue(), REF_UINT64);
824     ASSERT_EQ(pandArgs.pald->GetValue().size(), REF_DLIST.size());
825     for (std::size_t i = 0; i < REF_DLIST.size(); ++i) {
826         EXPECT_EQ(pandArgs.pald->GetValue()[i], REF_DLIST[i]);
827     }
828     EXPECT_EQ(pandArgs.pair->GetValue(), REF_INT);
829     EXPECT_EQ(pandArgs.paur32->GetValue(), REF_UINT32R);
830     EXPECT_EQ(pandArgs.paur64->GetValue(), REF_UINT64R);
831     EXPECT_EQ(tPandArgs.tPas->GetValue(), REF_T_STR1);
832     EXPECT_EQ(tPas0.GetValue(), REF_T_STR2);
833     EXPECT_EQ(tPas1.GetValue(), REF_T_STR3);
834     arg_list_t remainder = paParser.GetRemainder();
835     EXPECT_EQ(remainder.size(), REF_REM.size());
836     for (std::size_t i = 0; i < remainder.size(); i++) {
837         EXPECT_EQ(remainder[i], REF_REM[i]);
838     }
839     paParser.DisableRemainder();
840     paParser.DisableTail();
841     paParser.EraseTail();
842 }
843 
TestHexValues(PandArgParser & paParser,TestPandArgs & pandArgs)844 static void TestHexValues(PandArgParser &paParser, TestPandArgs &pandArgs)
845 {
846     // expect hex values processed right
847     {
848         static constexpr const uint64_t REF_UINT64 = 274877906959;
849         static constexpr const int REF_INT = 64;
850         static constexpr const int ARGC_UINT64_INT = 3;
851         static const char *argvUint64Int[ARGC_UINT64_INT];
852         argvUint64Int[0U] = "gtest_app";
853         std::string s = "--" + pandArgs.pau64->GetName();
854         argvUint64Int[1U] = s.c_str();
855         argvUint64Int[2U] = "0x400000000f";
856         EXPECT_TRUE(paParser.Parse(ARGC_UINT64_INT, argvUint64Int));
857         EXPECT_EQ(pandArgs.pau64->GetValue(), REF_UINT64);
858         argvUint64Int[2U] = "0x40";
859         EXPECT_TRUE(paParser.Parse(ARGC_UINT64_INT, argvUint64Int));
860         EXPECT_EQ(pandArgs.pau64->GetValue(), REF_INT);
861     }
862 
863     {
864         static constexpr const uint64_t REF_UINT64 = 274877906944;
865         static constexpr const int REF_INT = 64;
866         static constexpr const int ARGC_UINT64_INT = 3;
867         static const char *argvUint64Int[ARGC_UINT64_INT];
868         argvUint64Int[0U] = "gtest_app";
869         std::string s = "--" + pandArgs.pau64->GetName();
870         argvUint64Int[1U] = s.c_str();
871         argvUint64Int[2U] = "0x4000000000";
872         EXPECT_TRUE(paParser.Parse(ARGC_UINT64_INT, argvUint64Int));
873         EXPECT_EQ(pandArgs.pau64->GetValue(), REF_UINT64);
874         argvUint64Int[2U] = "0x40";
875         EXPECT_TRUE(paParser.Parse(ARGC_UINT64_INT, argvUint64Int));
876         EXPECT_EQ(pandArgs.pau64->GetValue(), REF_INT);
877     }
878 }
879 
RunAPITests(PandArgParser & paParser,TestPandArgs & pandArgs,TestTailPandArgs & tPandArgs,const std::string & refDefStr)880 static void RunAPITests(PandArgParser &paParser, TestPandArgs &pandArgs, TestTailPandArgs &tPandArgs,
881                         const std::string &refDefStr)
882 {
883     TestArgSet(paParser, pandArgs);
884 
885     TestTypeConsistency(pandArgs, refDefStr);
886 
887     TestDublicate(paParser);
888 
889     TestTailFunctions(paParser, tPandArgs);
890 
891     TestHelpStringAndArgsList(paParser, pandArgs);
892 
893     TestBoolean(paParser, pandArgs);
894 
895     TestSignedValues(paParser, pandArgs);
896 
897     TestIntValues(paParser, pandArgs);
898 
899     TestHexValues(paParser, pandArgs);
900 
901     TestOutOfRangeInt(paParser, pandArgs);
902 
903     TestStringArg(paParser, pandArgs);
904 
905     TestListArg(paParser, pandArgs);
906 
907     TestDelimiterListArg(paParser, pandArgs);
908 
909     TestSignedIntWihRange(paParser, pandArgs);
910 
911     TestUInt32WihRange(paParser, pandArgs);
912 
913     TestUInt64WihRange(paParser, pandArgs);
914 
915     TestEmptyString(paParser, pandArgs);
916 
917     TestTailConsistency(paParser, tPandArgs);
918 
919     TestWrongTailArg(paParser, tPandArgs);
920 
921     TestTailAfterString(paParser, pandArgs, tPandArgs);
922 
923     TestTailAfterList(paParser, pandArgs, tPandArgs);
924 
925     TestTailAfterNoparamBoolean(paParser, pandArgs, tPandArgs, refDefStr);
926 
927     TestTailExceedsArgsNum(paParser, tPandArgs, refDefStr);
928 
929     TestTailRemainder(paParser, pandArgs);
930 
931     TestAllArgs(paParser, pandArgs, tPandArgs, refDefStr);
932 }
933 
AddArgsToParser(PandArgParser & paParser,TestPandArgs & pandArgs)934 static void AddArgsToParser(PandArgParser &paParser, TestPandArgs &pandArgs)
935 {
936     EXPECT_TRUE(paParser.Add(pandArgs.pab));
937     EXPECT_TRUE(paParser.Add(pandArgs.pai));
938     EXPECT_TRUE(paParser.Add(pandArgs.pad));
939     EXPECT_TRUE(paParser.Add(pandArgs.pas));
940     EXPECT_TRUE(paParser.Add(pandArgs.pau32));
941     EXPECT_TRUE(paParser.Add(pandArgs.pau64));
942     EXPECT_TRUE(paParser.Add(pandArgs.pald));
943     EXPECT_TRUE(paParser.Add(pandArgs.pal));
944     EXPECT_TRUE(paParser.Add(pandArgs.pair));
945     EXPECT_TRUE(paParser.Add(pandArgs.paur32));
946     EXPECT_TRUE(paParser.Add(pandArgs.paur64));
947 }
948 
TEST(libpandargs,TestAPI)949 TEST(libpandargs, TestAPI)
950 {
951     static const std::string REF_DEF_STRING = "noarg";
952     static const arg_list_t REF_DEF_DLIST = arg_list_t();
953     static const arg_list_t REF_DEF_LIST = arg_list_t();
954 
955     PandArg<bool> pab("bool", REF_DEF_BOOL, "Sample boolean argument");
956     PandArg<int> pai("int", REF_DEF_INT, "Sample integer argument");
957     PandArg<double> pad("double", REF_DEF_DOUBLE, "Sample rational argument");
958     PandArg<std::string> pas("string", REF_DEF_STRING, "Sample string argument");
959     PandArg<uint32_t> pau32("uint32", REF_DEF_UINT32, "Sample uint32 argument");
960     PandArg<uint64_t> pau64("uint64", REF_DEF_UINT64, "Sample uint64 argument");
961     PandArg<arg_list_t> pald("dlist", REF_DEF_DLIST, "Sample delimiter list argument", ":");
962     PandArg<arg_list_t> pal("list", REF_DEF_LIST, "Sample list argument");
963     // NOLINTNEXTLINE(readability-magic-numbers)
964     PandArg<int> pair("rint", REF_DEF_INT, "Integer argument with range", -100L, 100U);
965     // NOLINTNEXTLINE(readability-magic-numbers)
966     PandArg<uint32_t> paur32("ruint32", REF_DEF_UINT64, "uint32 argument with range", 0U, 1000000000U);
967     // NOLINTNEXTLINE(readability-magic-numbers)
968     PandArg<uint64_t> paur64("ruint64", REF_DEF_UINT64, "uint64 argument with range", 0U, 100000000000U);
969 
970     TestPandArgs pandArgs {};
971     pandArgs.pab = &pab;
972     pandArgs.pai = &pai;
973     pandArgs.pad = &pad;
974     pandArgs.pas = &pas;
975     pandArgs.pau32 = &pau32;
976     pandArgs.pau64 = &pau64;
977     pandArgs.pald = &pald;
978     pandArgs.pal = &pal;
979     pandArgs.pair = &pair;
980     pandArgs.paur32 = &paur32;
981     pandArgs.paur64 = &paur64;
982 
983     PandArgParser paParser;
984     AddArgsToParser(paParser, pandArgs);
985 
986     PandArg<bool> tPab("tail_bool", REF_DEF_BOOL, "Sample tail boolean argument");
987     PandArg<int> tPai("tail_int", REF_DEF_INT, "Sample tail integer argument");
988     PandArg<double> tPad("tail_double", REF_DEF_DOUBLE, "Sample tail rational argument");
989     PandArg<std::string> tPas("tail_string", REF_DEF_STRING, "Sample tail string argument");
990     PandArg<uint32_t> tPau32("tail_uint32", REF_DEF_UINT32, "Sample tail uint32 argument");
991     PandArg<uint64_t> tPau64("tail_uint64", REF_DEF_UINT64, "Sample tail uint64 argument");
992 
993     TestTailPandArgs tPandArgs {};
994     tPandArgs.tPab = &tPab;
995     tPandArgs.tPai = &tPai;
996     tPandArgs.tPad = &tPad;
997     tPandArgs.tPas = &tPas;
998     tPandArgs.tPau32 = &tPau32;
999     tPandArgs.tPau64 = &tPau64;
1000 
1001     RunAPITests(paParser, pandArgs, tPandArgs, REF_DEF_STRING);
1002 }
1003 
TEST(libpandargs,NoSubArgs)1004 TEST(libpandargs, NoSubArgs)
1005 {
1006     PandArg<bool> subBoolArg("bool", false, "Sample boolean argument");
1007     // NOLINTNEXTLINE(readability-magic-numbers)
1008     PandArg<int> subIntArg("int", 12U, "Sample integer argument");
1009     // NOLINTNEXTLINE(readability-magic-numbers)
1010     PandArg<double> subDoubleArg("double", 123.45, "Sample rational argument");
1011     PandArg<std::string> subStringArg("string", "Hello", "Sample string argument");
1012     // NOLINTNEXTLINE(readability-magic-numbers)
1013     PandArg<int> intArg("global_int", 123U, "Global integer argument");
1014     PandArgCompound parent("compound", "Sample boolean argument",
1015                            {&subBoolArg, &subIntArg, &subDoubleArg, &subStringArg});
1016 
1017     PandArgParser paParser;
1018     ASSERT_TRUE(paParser.Add(&intArg));
1019     ASSERT_TRUE(paParser.Add(&parent));
1020 
1021     /* Should work well with no sub arguments */
1022     {
1023         parent.ResetDefaultValue();
1024         static const char *argv[] = {"gtest_app", "--compound"};
1025         ASSERT_TRUE(paParser.Parse(2U, argv)) << paParser.GetErrorString();
1026         ASSERT_EQ(parent.GetValue(), true);
1027         ASSERT_EQ(subBoolArg.GetValue(), false);
1028         ASSERT_EQ(subIntArg.GetValue(), 12U);
1029         ASSERT_EQ(subDoubleArg.GetValue(), 123.45);
1030         ASSERT_EQ(subStringArg.GetValue(), "Hello");
1031     }
1032 
1033     {
1034         parent.ResetDefaultValue();
1035         static const char *argv[] = {"gtest_app", "--compound:bool,int=2,double=54.321,string=World"};
1036         ASSERT_TRUE(paParser.Parse(2U, argv)) << paParser.GetErrorString();
1037         ASSERT_EQ(parent.GetValue(), true);
1038         ASSERT_EQ(subBoolArg.GetValue(), true);
1039         ASSERT_EQ(subIntArg.GetValue(), 2U);
1040         ASSERT_EQ(subDoubleArg.GetValue(), 54.321);
1041         ASSERT_EQ(subStringArg.GetValue(), "World");
1042     }
1043 }
1044 
TEST(libpandargs,ResetSubArgs)1045 TEST(libpandargs, ResetSubArgs)
1046 {
1047     PandArg<bool> subBoolArg("bool", false, "Sample boolean argument");
1048     // NOLINTNEXTLINE(readability-magic-numbers)
1049     PandArg<int> subIntArg("int", 12U, "Sample integer argument");
1050     // NOLINTNEXTLINE(readability-magic-numbers)
1051     PandArg<double> subDoubleArg("double", 123.45, "Sample rational argument");
1052     PandArg<std::string> subStringArg("string", "Hello", "Sample string argument");
1053     // NOLINTNEXTLINE(readability-magic-numbers)
1054     PandArg<int> intArg("global_int", 123U, "Global integer argument");
1055     PandArgCompound parent("compound", "Sample boolean argument",
1056                            {&subBoolArg, &subIntArg, &subDoubleArg, &subStringArg});
1057 
1058     PandArgParser paParser;
1059     ASSERT_TRUE(paParser.Add(&intArg));
1060     ASSERT_TRUE(paParser.Add(&parent));
1061 
1062     /* ResetDefaultValue should reset all sub arguments */
1063     parent.ResetDefaultValue();
1064     ASSERT_EQ(parent.GetValue(), false);
1065     ASSERT_EQ(subBoolArg.GetValue(), false);
1066     ASSERT_EQ(subIntArg.GetValue(), 12U);
1067     ASSERT_EQ(subDoubleArg.GetValue(), 123.45);
1068     ASSERT_EQ(subStringArg.GetValue(), "Hello");
1069 
1070     static const char *argv1[] = {"gtest_app", "--compound:bool=true"};
1071     ASSERT_TRUE(paParser.Parse(2U, argv1)) << paParser.GetErrorString();
1072     ASSERT_EQ(parent.GetValue(), true);
1073     ASSERT_EQ(subBoolArg.GetValue(), true);
1074 
1075     parent.ResetDefaultValue();
1076     static const char *argv2[] = {"gtest_app", "--compound:bool"};
1077     ASSERT_TRUE(paParser.Parse(2U, argv2)) << paParser.GetErrorString();
1078     ASSERT_EQ(parent.GetValue(), true);
1079     ASSERT_EQ(subBoolArg.GetValue(), true);
1080 
1081     static const char *argv3[] = {"gtest_app", "--compound:bool=false"};
1082     ASSERT_TRUE(paParser.Parse(2U, argv3)) << paParser.GetErrorString();
1083     ASSERT_EQ(parent.GetValue(), true);
1084     ASSERT_EQ(subBoolArg.GetValue(), false);
1085 
1086     parent.ResetDefaultValue();
1087     static const char *argv4[] = {"gtest_app", "--global_int=321"};
1088     ASSERT_TRUE(paParser.Parse(2U, argv4)) << paParser.GetErrorString();
1089     ASSERT_EQ(parent.GetValue(), false);
1090     ASSERT_EQ(intArg.GetValue(), 321U);
1091 
1092     parent.ResetDefaultValue();
1093     static const char *argv5[] = {"gtest_app", "--compound", "--global_int", "321"};
1094     ASSERT_TRUE(paParser.Parse(4U, argv5)) << paParser.GetErrorString();
1095     ASSERT_EQ(parent.GetValue(), true);
1096     ASSERT_EQ(intArg.GetValue(), 321U);
1097 }
1098 
TEST(libpandargs,SubArgsVisibility)1099 TEST(libpandargs, SubArgsVisibility)
1100 {
1101     PandArg<bool> subBoolArg("bool", false, "Sample boolean argument");
1102     // NOLINTNEXTLINE(readability-magic-numbers)
1103     PandArg<int> subIntArg("int", 12U, "Sample integer argument");
1104     // NOLINTNEXTLINE(readability-magic-numbers)
1105     PandArg<double> subDoubleArg("double", 123.45, "Sample rational argument");
1106     PandArg<std::string> subStringArg("string", "Hello", "Sample string argument");
1107     // NOLINTNEXTLINE(readability-magic-numbers)
1108     PandArg<int> intArg("global_int", 123U, "Global integer argument");
1109     PandArgCompound parent("compound", "Sample boolean argument",
1110                            {&subBoolArg, &subIntArg, &subDoubleArg, &subStringArg});
1111 
1112     PandArgParser paParser;
1113     ASSERT_TRUE(paParser.Add(&intArg));
1114     ASSERT_TRUE(paParser.Add(&parent));
1115 
1116     /* Test that sub arguments are not visible in the global space */
1117     {
1118         static const char *argv[] = {"gtest_app", "--bool"};
1119         ASSERT_FALSE(paParser.Parse(2U, argv));
1120     }
1121     {
1122         static const char *argv[] = {"gtest_app", "--int=2"};
1123         ASSERT_FALSE(paParser.Parse(2U, argv));
1124     }
1125     {
1126         static const char *argv[] = {"gtest_app", "--double=54.321"};
1127         ASSERT_FALSE(paParser.Parse(2U, argv));
1128     }
1129     {
1130         static const char *argv[] = {"gtest_app", "--string=World"};
1131         ASSERT_FALSE(paParser.Parse(2U, argv));
1132     }
1133 }
1134 
TEST(libpandargs,IncorrectCompoundArgs)1135 TEST(libpandargs, IncorrectCompoundArgs)
1136 {
1137     static const arg_list_t REF_DEF_LIST = arg_list_t();
1138     PandArg<arg_list_t> pal("list", REF_DEF_LIST, "Sample list argument");
1139 
1140     PandArgParser paParser;
1141     EXPECT_TRUE(paParser.Add(&pal));
1142     pal.ResetDefaultValue();
1143 
1144     /* Test that incorrect using of compound argument syntax for non-compound argument produces error*/
1145     static const char *argv[] = {"gtest_app", "--list:list_arg1:list_arg2"};
1146     ASSERT_FALSE(paParser.Parse(2U, argv)) << paParser.GetErrorString();
1147 }
1148 
TEST(libpandargs,IncorrectIntArgs)1149 TEST(libpandargs, IncorrectIntArgs)
1150 {
1151     PandArg<int> pai("int", 0, "Sample int argument");
1152     PandArg<uint32_t> pau32("uint32", 0, "Sample uin32 argument");
1153     PandArg<uint64_t> pau64("uint64", 0, "Sample uin64 argument");
1154 
1155     PandArgParser paParser;
1156     EXPECT_TRUE(paParser.Add(&pai));
1157     EXPECT_TRUE(paParser.Add(&pau32));
1158     EXPECT_TRUE(paParser.Add(&pau64));
1159 
1160     {
1161         static const char *argv[] = {"int", "20000000000000000000"};  // > 2^64
1162         ASSERT_FALSE(paParser.Parse(2U, argv)) << paParser.GetErrorString();
1163     }
1164     {
1165         static const char *argv[] = {"uint32", "5000000000"};  // > 2^32
1166         ASSERT_FALSE(paParser.Parse(2U, argv)) << paParser.GetErrorString();
1167     }
1168     {
1169         static const char *argv[] = {"uint64", "20000000000000000000"};  // > 2^64
1170         ASSERT_FALSE(paParser.Parse(2U, argv)) << paParser.GetErrorString();
1171     }
1172 }
1173 
1174 // NOLINTEND(modernize-avoid-c-arrays)
1175 
1176 }  // namespace ark::test
1177