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