1 // Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
2 // under NSF AWARD 1414736 and by the respective contributors.
3 // All rights reserved.
4 //
5 // SPDX-License-Identifier: BSD-3-Clause
6 
7 #include "app_helper.hpp"
8 #include <complex>
9 #include <cstdint>
10 #include <cstdlib>
11 
12 TEST_CASE_METHOD(TApp, "OneFlagShort", "[app]") {
13     app.add_flag("-c,--count");
14     args = {"-c"};
15     run();
16     CHECK(app.count("-c") == 1u);
17     CHECK(app.count("--count") == 1u);
18 }
19 
20 TEST_CASE_METHOD(TApp, "OneFlagShortValues", "[app]") {
21     app.add_flag("-c{v1},--count{v2}");
22     args = {"-c"};
23     run();
24     CHECK(app.count("-c") == 1u);
25     CHECK(app.count("--count") == 1u);
26     auto v = app["-c"]->results();
27     CHECK("v1" == v[0]);
28 
29     CHECK_THROWS_AS(app["--invalid"], CLI::OptionNotFound);
30 }
31 
32 TEST_CASE_METHOD(TApp, "OneFlagShortValuesAs", "[app]") {
33     auto flg = app.add_flag("-c{1},--count{2}");
34     args = {"-c"};
35     run();
36     auto opt = app["-c"];
37     CHECK(1 == opt->as<int>());
38     args = {"--count"};
39     run();
40     CHECK(2 == opt->as<int>());
41     flg->take_first();
42     args = {"-c", "--count"};
43     run();
44     CHECK(1 == opt->as<int>());
45     flg->take_last();
46     CHECK(2 == opt->as<int>());
47     flg->multi_option_policy(CLI::MultiOptionPolicy::Throw);
48     CHECK_THROWS_AS(opt->as<int>(), CLI::ArgumentMismatch);
49     flg->multi_option_policy(CLI::MultiOptionPolicy::TakeAll);
50     auto vec = opt->as<std::vector<int>>();
51     CHECK(1 == vec[0]);
52     CHECK(2 == vec[1]);
53     flg->multi_option_policy(CLI::MultiOptionPolicy::Join);
54     CHECK("1\n2" == opt->as<std::string>());
55     flg->delimiter(',');
56     CHECK("1,2" == opt->as<std::string>());
57 }
58 
59 TEST_CASE_METHOD(TApp, "OneFlagShortWindows", "[app]") {
60     app.add_flag("-c,--count");
61     args = {"/c"};
62     app.allow_windows_style_options();
63     run();
64     CHECK(app.count("-c") == 1u);
65     CHECK(app.count("--count") == 1u);
66 }
67 
68 TEST_CASE_METHOD(TApp, "WindowsLongShortMix1", "[app]") {
69     app.allow_windows_style_options();
70 
71     auto a = app.add_flag("-c");
72     auto b = app.add_flag("--c");
73     args = {"/c"};
74     run();
75     CHECK(a->count() == 1u);
76     CHECK(b->count() == 0u);
77 }
78 
79 TEST_CASE_METHOD(TApp, "WindowsLongShortMix2", "[app]") {
80     app.allow_windows_style_options();
81 
82     auto a = app.add_flag("--c");
83     auto b = app.add_flag("-c");
84     args = {"/c"};
85     run();
86     CHECK(a->count() == 1u);
87     CHECK(b->count() == 0u);
88 }
89 
90 TEST_CASE_METHOD(TApp, "CountNonExist", "[app]") {
91     app.add_flag("-c,--count");
92     args = {"-c"};
93     run();
94     CHECK_THROWS_AS(app.count("--nonexist"), CLI::OptionNotFound);
95 }
96 
97 TEST_CASE_METHOD(TApp, "OneFlagLong", "[app]") {
98     app.add_flag("-c,--count");
99     args = {"--count"};
100     run();
101     CHECK(app.count("-c") == 1u);
102     CHECK(app.count("--count") == 1u);
103 }
104 
105 TEST_CASE_METHOD(TApp, "DashedOptions", "[app]") {
106     app.add_flag("-c");
107     app.add_flag("--q");
108     app.add_flag("--this,--that");
109 
110     args = {"-c", "--q", "--this", "--that"};
111     run();
112     CHECK(app.count("-c") == 1u);
113     CHECK(app.count("--q") == 1u);
114     CHECK(app.count("--this") == 2u);
115     CHECK(app.count("--that") == 2u);
116 }
117 
118 TEST_CASE_METHOD(TApp, "DashedOptionsSingleString", "[app]") {
119     app.add_flag("-c");
120     app.add_flag("--q");
121     app.add_flag("--this,--that");
122 
123     app.parse("-c --q --this --that");
124     CHECK(app.count("-c") == 1u);
125     CHECK(app.count("--q") == 1u);
126     CHECK(app.count("--this") == 2u);
127     CHECK(app.count("--that") == 2u);
128 }
129 
130 TEST_CASE_METHOD(TApp, "StrangeFlagNames", "[app]") {
131     app.add_flag("-=");
132     app.add_flag("--t\tt");
133     app.add_flag("-{");
134     CHECK_THROWS_AS(app.add_flag("--t t"), CLI::ConstructionError);
135     args = {"-=", "--t\tt"};
136     run();
137     CHECK(app.count("-=") == 1u);
138     CHECK(app.count("--t\tt") == 1u);
139 }
140 
141 TEST_CASE_METHOD(TApp, "RequireOptionsError", "[app]") {
142     using Catch::Matchers::Contains;
143 
144     app.add_flag("-c");
145     app.add_flag("--q");
146     app.add_flag("--this,--that");
147     app.set_help_flag("-h,--help");
148     app.set_help_all_flag("--help_all");
149     app.require_option(1, 2);
150     try {
151         app.parse("-c --q --this --that");
152     } catch(const CLI::RequiredError &re) {
153         CHECK_THAT(re.what(), !Contains("-h,--help"));
154         CHECK_THAT(re.what(), !Contains("help_all"));
155     }
156 
157     CHECK_NOTHROW(app.parse("-c --q"));
158     CHECK_NOTHROW(app.parse("-c --this --that"));
159 }
160 
161 TEST_CASE_METHOD(TApp, "BoolFlagOverride", "[app]") {
162     bool val{false};
163     auto flg = app.add_flag("--this,--that", val);
164 
165     app.parse("--this");
166     CHECK(val);
167     app.parse("--this=false");
168     CHECK(!val);
169     flg->disable_flag_override(true);
170     app.parse("--this");
171     CHECK(val);
172     // this is allowed since the matching string is the default
173     app.parse("--this=true");
174     CHECK(val);
175 
176     CHECK_THROWS_AS(app.parse("--this=false"), CLI::ArgumentMismatch);
177     // try a string that specifies 'use default val'
178     CHECK_NOTHROW(app.parse("--this={}"));
179 }
180 
181 TEST_CASE_METHOD(TApp, "OneFlagRef", "[app]") {
182     int ref{0};
183     app.add_flag("-c,--count", ref);
184     args = {"--count"};
185     run();
186     CHECK(app.count("-c") == 1u);
187     CHECK(app.count("--count") == 1u);
188     CHECK(ref == 1);
189 }
190 
191 TEST_CASE_METHOD(TApp, "OneFlagRefValue", "[app]") {
192     int ref{0};
193     app.add_flag("-c,--count", ref);
194     args = {"--count=7"};
195     run();
196     CHECK(app.count("-c") == 1u);
197     CHECK(app.count("--count") == 1u);
198     CHECK(ref == 7);
199 }
200 
201 TEST_CASE_METHOD(TApp, "OneFlagRefValueFalse", "[app]") {
202     int ref{0};
203     auto flg = app.add_flag("-c,--count", ref);
204     args = {"--count=false"};
205     run();
206     CHECK(app.count("-c") == 1u);
207     CHECK(app.count("--count") == 1u);
208     CHECK(ref == -1);
209 
210     CHECK(!flg->check_fname("c"));
211     args = {"--count=0"};
212     run();
213     CHECK(app.count("-c") == 1u);
214     CHECK(app.count("--count") == 1u);
215     CHECK(ref == -1);
216 
217     args = {"--count=happy"};
218     CHECK_THROWS_AS(run(), CLI::ConversionError);
219 }
220 
221 TEST_CASE_METHOD(TApp, "FlagNegation", "[app]") {
222     int ref{0};
223     auto flg = app.add_flag("-c,--count,--ncount{false}", ref);
224     args = {"--count", "-c", "--ncount"};
225     CHECK(!flg->check_fname("count"));
226     CHECK(flg->check_fname("ncount"));
227     run();
228     CHECK(app.count("-c") == 3u);
229     CHECK(app.count("--count") == 3u);
230     CHECK(app.count("--ncount") == 3u);
231     CHECK(ref == 1);
232 }
233 
234 TEST_CASE_METHOD(TApp, "FlagNegationShortcutNotation", "[app]") {
235     int ref{0};
236     app.add_flag("-c,--count{true},!--ncount", ref);
237     args = {"--count=TRUE", "-c", "--ncount"};
238     run();
239     CHECK(app.count("-c") == 3u);
240     CHECK(app.count("--count") == 3u);
241     CHECK(app.count("--ncount") == 3u);
242     CHECK(ref == 1);
243 }
244 
245 TEST_CASE_METHOD(TApp, "FlagNegationShortcutNotationInvalid", "[app]") {
246     int ref{0};
247     app.add_flag("-c,--count,!--ncount", ref);
248     args = {"--ncount=happy"};
249     CHECK_THROWS_AS(run(), CLI::ConversionError);
250 }
251 
252 TEST_CASE_METHOD(TApp, "OneString", "[app]") {
253     std::string str;
254     app.add_option("-s,--string", str);
255     args = {"--string", "mystring"};
256     run();
257     CHECK(app.count("-s") == 1u);
258     CHECK(app.count("--string") == 1u);
259     CHECK("mystring" == str);
260 }
261 
262 TEST_CASE_METHOD(TApp, "OneStringWindowsStyle", "[app]") {
263     std::string str;
264     app.add_option("-s,--string", str);
265     args = {"/string", "mystring"};
266     app.allow_windows_style_options();
267     run();
268     CHECK(app.count("-s") == 1u);
269     CHECK(app.count("--string") == 1u);
270     CHECK("mystring" == str);
271 }
272 
273 TEST_CASE_METHOD(TApp, "OneStringSingleStringInput", "[app]") {
274     std::string str;
275     app.add_option("-s,--string", str);
276 
277     app.parse("--string mystring");
278     CHECK(app.count("-s") == 1u);
279     CHECK(app.count("--string") == 1u);
280     CHECK("mystring" == str);
281 }
282 
283 TEST_CASE_METHOD(TApp, "OneStringEqualVersion", "[app]") {
284     std::string str;
285     app.add_option("-s,--string", str);
286     args = {"--string=mystring"};
287     run();
288     CHECK(app.count("-s") == 1u);
289     CHECK(app.count("--string") == 1u);
290     CHECK("mystring" == str);
291 }
292 
293 TEST_CASE_METHOD(TApp, "OneStringEqualVersionWindowsStyle", "[app]") {
294     std::string str;
295     app.add_option("-s,--string", str);
296     args = {"/string:mystring"};
297     app.allow_windows_style_options();
298     run();
299     CHECK(app.count("-s") == 1u);
300     CHECK(app.count("--string") == 1u);
301     CHECK("mystring" == str);
302 }
303 
304 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleString", "[app]") {
305     std::string str;
306     app.add_option("-s,--string", str);
307     app.parse("--string=mystring");
308     CHECK(app.count("-s") == 1u);
309     CHECK(app.count("--string") == 1u);
310     CHECK("mystring" == str);
311 }
312 
313 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuoted", "[app]") {
314     std::string str;
315     app.add_option("-s,--string", str);
316     app.parse(R"raw(--string="this is my quoted string")raw");
317     CHECK(app.count("-s") == 1u);
318     CHECK(app.count("--string") == 1u);
319     CHECK("this is my quoted string" == str);
320 }
321 
322 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuotedMultiple", "[app]") {
323     std::string str, str2, str3;
324     app.add_option("-s,--string", str);
325     app.add_option("-t,--tstr", str2);
326     app.add_option("-m,--mstr", str3);
327     app.parse(R"raw(--string="this is my quoted string" -t 'qstring 2' -m=`"quoted string"`)raw");
328     CHECK("this is my quoted string" == str);
329     CHECK("qstring 2" == str2);
330     CHECK("\"quoted string\"" == str3);
331 }
332 
333 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringEmbeddedEqual", "[app]") {
334     std::string str, str2, str3;
335     app.add_option("-s,--string", str);
336     app.add_option("-t,--tstr", str2);
337     app.add_option("-m,--mstr", str3);
338     app.parse(R"raw(--string="app=\"test1 b\" test2=\"frogs\"" -t 'qstring 2' -m=`"quoted string"`)raw");
339     CHECK("app=\"test1 b\" test2=\"frogs\"" == str);
340     CHECK("qstring 2" == str2);
341     CHECK("\"quoted string\"" == str3);
342 
343     app.parse(R"raw(--string="app='test1 b' test2='frogs'" -t 'qstring 2' -m=`"quoted string"`)raw");
344     CHECK("app='test1 b' test2='frogs'" == str);
345     CHECK("qstring 2" == str2);
346     CHECK("\"quoted string\"" == str3);
347 }
348 
349 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringEmbeddedEqualWindowsStyle", "[app]") {
350     std::string str, str2, str3;
351     app.add_option("-s,--string", str);
352     app.add_option("-t,--tstr", str2);
353     app.add_option("--mstr", str3);
354     app.allow_windows_style_options();
355     app.parse(R"raw(/string:"app:\"test1 b\" test2:\"frogs\"" /t 'qstring 2' /mstr:`"quoted string"`)raw");
356     CHECK("app:\"test1 b\" test2:\"frogs\"" == str);
357     CHECK("qstring 2" == str2);
358     CHECK("\"quoted string\"" == str3);
359 
360     app.parse(R"raw(/string:"app:'test1 b' test2:'frogs'" /t 'qstring 2' /mstr:`"quoted string"`)raw");
361     CHECK("app:'test1 b' test2:'frogs'" == str);
362     CHECK("qstring 2" == str2);
363     CHECK("\"quoted string\"" == str3);
364 }
365 
366 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuotedMultipleMixedStyle", "[app]") {
367     std::string str, str2, str3;
368     app.add_option("-s,--string", str);
369     app.add_option("-t,--tstr", str2);
370     app.add_option("-m,--mstr", str3);
371     app.allow_windows_style_options();
372     app.parse(R"raw(/string:"this is my quoted string" /t 'qstring 2' -m=`"quoted string"`)raw");
373     CHECK("this is my quoted string" == str);
374     CHECK("qstring 2" == str2);
375     CHECK("\"quoted string\"" == str3);
376 }
377 
378 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuotedMultipleInMiddle", "[app]") {
379     std::string str, str2, str3;
380     app.add_option("-s,--string", str);
381     app.add_option("-t,--tstr", str2);
382     app.add_option("-m,--mstr", str3);
383     app.parse(R"raw(--string="this is my quoted string" -t "qst\"ring 2" -m=`"quoted string"`)raw");
384     CHECK("this is my quoted string" == str);
385     CHECK("qst\"ring 2" == str2);
386     CHECK("\"quoted string\"" == str3);
387 }
388 
389 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuotedEscapedCharacters", "[app]") {
390     std::string str, str2, str3;
391     app.add_option("-s,--string", str);
392     app.add_option("-t,--tstr", str2);
393     app.add_option("-m,--mstr", str3);
394     app.parse(R"raw(--string="this is my \"quoted\" string" -t 'qst\'ring 2' -m=`"quoted\` string"`")raw");
395     CHECK("this is my \"quoted\" string" == str);
396     CHECK("qst\'ring 2" == str2);
397     CHECK("\"quoted` string\"" == str3);
398 }
399 
400 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuotedMultipleWithEqual", "[app]") {
401     std::string str, str2, str3, str4;
402     app.add_option("-s,--string", str);
403     app.add_option("-t,--tstr", str2);
404     app.add_option("-m,--mstr", str3);
405     app.add_option("-j,--jstr", str4);
406     app.parse(R"raw(--string="this is my quoted string" -t 'qstring 2' -m=`"quoted string"` --jstr=Unquoted)raw");
407     CHECK("this is my quoted string" == str);
408     CHECK("qstring 2" == str2);
409     CHECK("\"quoted string\"" == str3);
410     CHECK("Unquoted" == str4);
411 }
412 
413 TEST_CASE_METHOD(TApp, "OneStringEqualVersionSingleStringQuotedMultipleWithEqualAndProgram", "[app]") {
414     std::string str, str2, str3, str4;
415     app.add_option("-s,--string", str);
416     app.add_option("-t,--tstr", str2);
417     app.add_option("-m,--mstr", str3);
418     app.add_option("-j,--jstr", str4);
419     app.parse(
420         R"raw(program --string="this is my quoted string" -t 'qstring 2' -m=`"quoted string"` --jstr=Unquoted)raw",
421         true);
422     CHECK("this is my quoted string" == str);
423     CHECK("qstring 2" == str2);
424     CHECK("\"quoted string\"" == str3);
425     CHECK("Unquoted" == str4);
426 }
427 
428 TEST_CASE_METHOD(TApp, "OneStringFlagLike", "[app]") {
429     std::string str{"something"};
430     app.add_option("-s,--string", str)->expected(0, 1);
431     args = {"--string"};
432     run();
433     CHECK(app.count("-s") == 1u);
434     CHECK(app.count("--string") == 1u);
435     CHECK(str.empty());
436 }
437 
438 TEST_CASE_METHOD(TApp, "OneIntFlagLike", "[app]") {
439     int val{0};
440     auto opt = app.add_option("-i", val)->expected(0, 1);
441     args = {"-i"};
442     run();
443     CHECK(app.count("-i") == 1u);
444     opt->default_str("7");
445     run();
446     CHECK(7 == val);
447 
448     opt->default_val(9);
449     run();
450     CHECK(9 == val);
451 }
452 
453 TEST_CASE_METHOD(TApp, "TogetherInt", "[app]") {
454     int i{0};
455     app.add_option("-i,--int", i);
456     args = {"-i4"};
457     run();
458     CHECK(app.count("--int") == 1u);
459     CHECK(app.count("-i") == 1u);
460     CHECK(4 == i);
461     CHECK("4" == app["-i"]->as<std::string>());
462     CHECK(4.0 == app["--int"]->as<double>());
463 }
464 
465 TEST_CASE_METHOD(TApp, "SepInt", "[app]") {
466     int i{0};
467     app.add_option("-i,--int", i);
468     args = {"-i", "4"};
469     run();
470     CHECK(app.count("--int") == 1u);
471     CHECK(app.count("-i") == 1u);
472     CHECK(4 == i);
473 }
474 
475 TEST_CASE_METHOD(TApp, "DefaultStringAgain", "[app]") {
476     std::string str = "previous";
477     app.add_option("-s,--string", str);
478     run();
479     CHECK(app.count("-s") == 0u);
480     CHECK(app.count("--string") == 0u);
481     CHECK("previous" == str);
482 }
483 
484 TEST_CASE_METHOD(TApp, "DefaultStringAgainEmpty", "[app]") {
485     std::string str = "previous";
486     app.add_option("-s,--string", str);
487     app.parse("   ");
488     CHECK(app.count("-s") == 0u);
489     CHECK(app.count("--string") == 0u);
490     CHECK("previous" == str);
491 }
492 
493 TEST_CASE_METHOD(TApp, "DualOptions", "[app]") {
494 
495     std::string str = "previous";
496     std::vector<std::string> vstr = {"previous"};
497     std::vector<std::string> ans = {"one", "two"};
498     app.add_option("-s,--string", str);
499     app.add_option("-v,--vector", vstr);
500 
501     args = {"--vector=one", "--vector=two"};
502     run();
503     CHECK(vstr == ans);
504 
505     args = {"--string=one", "--string=two"};
506     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
507 }
508 
509 TEST_CASE_METHOD(TApp, "LotsOfFlags", "[app]") {
510 
511     app.add_flag("-a");
512     app.add_flag("-A");
513     app.add_flag("-b");
514 
515     args = {"-a", "-b", "-aA"};
516     run();
517     CHECK(app.count("-a") == 2u);
518     CHECK(app.count("-b") == 1u);
519     CHECK(app.count("-A") == 1u);
520     CHECK(4u == app.count_all());
521 }
522 
523 TEST_CASE_METHOD(TApp, "NumberFlags", "[app]") {
524 
525     int val{0};
526     app.add_flag("-1{1},-2{2},-3{3},-4{4},-5{5},-6{6}, -7{7}, -8{8}, -9{9}", val);
527 
528     args = {"-7"};
529     run();
530     CHECK(app.count("-1") == 1u);
531     CHECK(7 == val);
532 }
533 
534 TEST_CASE_METHOD(TApp, "DisableFlagOverrideTest", "[app]") {
535 
536     int val{0};
537     auto opt = app.add_flag("--1{1},--2{2},--3{3},--4{4},--5{5},--6{6}, --7{7}, --8{8}, --9{9}", val);
538     CHECK(!opt->get_disable_flag_override());
539     opt->disable_flag_override();
540     args = {"--7=5"};
541     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
542     CHECK(opt->get_disable_flag_override());
543     opt->disable_flag_override(false);
544     CHECK(!opt->get_disable_flag_override());
545     CHECK_NOTHROW(run());
546     CHECK(5 == val);
547     opt->disable_flag_override();
548     args = {"--7=7"};
549     CHECK_NOTHROW(run());
550 }
551 
552 TEST_CASE_METHOD(TApp, "LotsOfFlagsSingleString", "[app]") {
553 
554     app.add_flag("-a");
555     app.add_flag("-A");
556     app.add_flag("-b");
557 
558     app.parse("-a -b -aA");
559     CHECK(app.count("-a") == 2u);
560     CHECK(app.count("-b") == 1u);
561     CHECK(app.count("-A") == 1u);
562 }
563 
564 TEST_CASE_METHOD(TApp, "LotsOfFlagsSingleStringExtraSpace", "[app]") {
565 
566     app.add_flag("-a");
567     app.add_flag("-A");
568     app.add_flag("-b");
569 
570     app.parse("  -a    -b    -aA   ");
571     CHECK(app.count("-a") == 2u);
572     CHECK(app.count("-b") == 1u);
573     CHECK(app.count("-A") == 1u);
574 }
575 
576 TEST_CASE_METHOD(TApp, "SingleArgVector", "[app]") {
577 
578     std::vector<std::string> channels;
579     std::vector<std::string> iargs;
580     std::string path;
581     app.add_option("-c", channels)->type_size(1)->allow_extra_args(false);
582     app.add_option("args", iargs);
583     app.add_option("-p", path);
584 
585     app.parse("-c t1 -c t2 -c t3 a1 a2 a3 a4 -p happy");
586     CHECK(channels.size() == 3u);
587     CHECK(iargs.size() == 4u);
588     CHECK("happy" == path);
589 
590     app.parse("-c t1 a1 -c t2 -c t3 a2 a3 a4 -p happy");
591     CHECK(channels.size() == 3u);
592     CHECK(iargs.size() == 4u);
593     CHECK("happy" == path);
594 }
595 
596 TEST_CASE_METHOD(TApp, "StrangeOptionNames", "[app]") {
597     app.add_option("-:");
598     app.add_option("--t\tt");
599     app.add_option("--{}");
600     app.add_option("--:)");
601     CHECK_THROWS_AS(app.add_option("--t t"), CLI::ConstructionError);
602     args = {"-:)", "--{}", "5"};
603     run();
604     CHECK(app.count("-:") == 1u);
605     CHECK(app.count("--{}") == 1u);
606     CHECK(app["-:"]->as<char>() == ')');
607     CHECK(app["--{}"]->as<int>() == 5);
608 }
609 
610 TEST_CASE_METHOD(TApp, "FlagLikeOption", "[app]") {
611     bool val{false};
612     auto opt = app.add_option("--flag", val)->type_size(0)->default_str("true");
613     args = {"--flag"};
614     run();
615     CHECK(app.count("--flag") == 1u);
616     CHECK(val);
617     val = false;
618     opt->type_size(0, 0);  // should be the same as above
619     CHECK(0 == opt->get_type_size_min());
620     CHECK(0 == opt->get_type_size_max());
621     run();
622     CHECK(app.count("--flag") == 1u);
623     CHECK(val);
624 }
625 
626 TEST_CASE_METHOD(TApp, "FlagLikeIntOption", "[app]") {
627     int val{-47};
628     auto opt = app.add_option("--flag", val)->expected(0, 1);
629     // normally some default value should be set, but this test is for some paths in the validators checks to skip
630     // validation on empty string if nothing is expected
631     opt->check(CLI::PositiveNumber);
632     args = {"--flag"};
633     CHECK(opt->as<std::string>().empty());
634     run();
635     CHECK(app.count("--flag") == 1u);
636     CHECK(-47 != val);
637     args = {"--flag", "12"};
638     run();
639 
640     CHECK(12 == val);
641     args.clear();
642     run();
643     CHECK(opt->as<std::string>().empty());
644 }
645 
646 TEST_CASE_METHOD(TApp, "BoolOnlyFlag", "[app]") {
647     bool bflag{false};
648     app.add_flag("-b", bflag)->multi_option_policy(CLI::MultiOptionPolicy::Throw);
649 
650     args = {"-b"};
651     REQUIRE_NOTHROW(run());
652     CHECK(bflag);
653 
654     args = {"-b", "-b"};
655     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
656 }
657 
658 TEST_CASE_METHOD(TApp, "ShortOpts", "[app]") {
659 
660     std::uint64_t funnyint{0};
661     std::string someopt;
662     app.add_flag("-z", funnyint);
663     app.add_option("-y", someopt);
664 
665     args = {
666         "-zzyzyz",
667     };
668 
669     run();
670 
671     CHECK(app.count("-z") == 2u);
672     CHECK(app.count("-y") == 1u);
673     CHECK(funnyint == std::uint64_t{2});
674     CHECK(someopt == "zyz");
675     CHECK(3u == app.count_all());
676 }
677 
678 TEST_CASE_METHOD(TApp, "TwoParamTemplateOpts", "[app]") {
679 
680     double funnyint{0.0};
681     auto opt = app.add_option<double, unsigned int>("-y", funnyint);
682 
683     args = {"-y", "32"};
684 
685     run();
686 
687     CHECK(funnyint == 32.0);
688 
689     args = {"-y", "32.3"};
690     CHECK_THROWS_AS(run(), CLI::ConversionError);
691 
692     args = {"-y", "-19"};
693     CHECK_THROWS_AS(run(), CLI::ConversionError);
694 
695     opt->capture_default_str();
696     CHECK(opt->get_default_str().empty());
697 }
698 
699 TEST_CASE_METHOD(TApp, "DefaultOpts", "[app]") {
700 
701     int i{3};
702     std::string s = "HI";
703 
704     app.add_option("-i,i", i);
705     app.add_option("-s,s", s)->capture_default_str();  //  Used to be different
706 
707     args = {"-i2", "9"};
708 
709     run();
710 
711     CHECK(app.count("i") == 1u);
712     CHECK(app.count("-s") == 1u);
713     CHECK(i == 2);
714     CHECK(s == "9");
715 }
716 
717 TEST_CASE_METHOD(TApp, "TakeLastOpt", "[app]") {
718 
719     std::string str;
720     app.add_option("--str", str)->multi_option_policy(CLI::MultiOptionPolicy::TakeLast);
721 
722     args = {"--str=one", "--str=two"};
723 
724     run();
725 
726     CHECK("two" == str);
727 }
728 
729 TEST_CASE_METHOD(TApp, "TakeLastOpt2", "[app]") {
730 
731     std::string str;
732     app.add_option("--str", str)->take_last();
733 
734     args = {"--str=one", "--str=two"};
735 
736     run();
737 
738     CHECK("two" == str);
739 }
740 
741 TEST_CASE_METHOD(TApp, "TakeFirstOpt", "[app]") {
742 
743     std::string str;
744     app.add_option("--str", str)->multi_option_policy(CLI::MultiOptionPolicy::TakeFirst);
745 
746     args = {"--str=one", "--str=two"};
747 
748     run();
749 
750     CHECK("one" == str);
751 }
752 
753 TEST_CASE_METHOD(TApp, "TakeFirstOpt2", "[app]") {
754 
755     std::string str;
756     app.add_option("--str", str)->take_first();
757 
758     args = {"--str=one", "--str=two"};
759 
760     run();
761 
762     CHECK("one" == str);
763 }
764 
765 TEST_CASE_METHOD(TApp, "JoinOpt", "[app]") {
766 
767     std::string str;
768     app.add_option("--str", str)->multi_option_policy(CLI::MultiOptionPolicy::Join);
769 
770     args = {"--str=one", "--str=two"};
771 
772     run();
773 
774     CHECK("one\ntwo" == str);
775 }
776 
777 TEST_CASE_METHOD(TApp, "JoinOpt2", "[app]") {
778 
779     std::string str;
780     app.add_option("--str", str)->join();
781 
782     args = {"--str=one", "--str=two"};
783 
784     run();
785 
786     CHECK("one\ntwo" == str);
787 }
788 
789 TEST_CASE_METHOD(TApp, "TakeLastOptMulti", "[app]") {
790     std::vector<int> vals;
791     app.add_option("--long", vals)->expected(2)->take_last();
792 
793     args = {"--long", "1", "2", "3"};
794 
795     run();
796 
797     CHECK(std::vector<int>({2, 3}) == vals);
798 }
799 
800 TEST_CASE_METHOD(TApp, "TakeLastOptMulti_alternative_path", "[app]") {
801     std::vector<int> vals;
802     app.add_option("--long", vals)->expected(2, -1)->take_last();
803 
804     args = {"--long", "1", "2", "3"};
805 
806     run();
807 
808     CHECK(std::vector<int>({2, 3}) == vals);
809 }
810 
811 TEST_CASE_METHOD(TApp, "TakeLastOptMultiCheck", "[app]") {
812     std::vector<int> vals;
813     auto opt = app.add_option("--long", vals)->expected(-2)->take_last();
814 
815     opt->check(CLI::Validator(CLI::PositiveNumber).application_index(0));
816     opt->check((!CLI::PositiveNumber).application_index(1));
817     args = {"--long", "-1", "2", "-3"};
818 
819     CHECK_NOTHROW(run());
820 
821     CHECK(std::vector<int>({2, -3}) == vals);
822 }
823 
824 TEST_CASE_METHOD(TApp, "TakeFirstOptMulti", "[app]") {
825     std::vector<int> vals;
826     app.add_option("--long", vals)->expected(2)->take_first();
827 
828     args = {"--long", "1", "2", "3"};
829 
830     run();
831 
832     CHECK(std::vector<int>({1, 2}) == vals);
833 }
834 
835 TEST_CASE_METHOD(TApp, "ComplexOptMulti", "[app]") {
836     std::complex<double> val;
837     app.add_option("--long", val)->take_first()->allow_extra_args();
838 
839     args = {"--long", "1", "2", "3", "4"};
840 
841     run();
842 
843     CHECK(1 == Approx(val.real()));
844     CHECK(2 == Approx(val.imag()));
845 }
846 
847 TEST_CASE_METHOD(TApp, "MissingValueNonRequiredOpt", "[app]") {
848     int count{0};
849     app.add_option("-c,--count", count);
850 
851     args = {"-c"};
852     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
853 
854     args = {"--count"};
855     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
856 }
857 
858 TEST_CASE_METHOD(TApp, "MissingValueMoreThan", "[app]") {
859     std::vector<int> vals1;
860     std::vector<int> vals2;
861     app.add_option("-v", vals1)->expected(-2);
862     app.add_option("--vals", vals2)->expected(-2);
863 
864     args = {"-v", "2"};
865     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
866 
867     args = {"--vals", "4"};
868     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
869 }
870 
871 TEST_CASE_METHOD(TApp, "NoMissingValueMoreThan", "[app]") {
872     std::vector<int> vals1;
873     std::vector<int> vals2;
874     app.add_option("-v", vals1)->expected(-2);
875     app.add_option("--vals", vals2)->expected(-2);
876 
877     args = {"-v", "2", "3", "4"};
878     run();
879     CHECK(std::vector<int>({2, 3, 4}) == vals1);
880 
881     args = {"--vals", "2", "3", "4"};
882     run();
883     CHECK(std::vector<int>({2, 3, 4}) == vals2);
884 }
885 
886 TEST_CASE_METHOD(TApp, "NotRequiredOptsSingle", "[app]") {
887 
888     std::string str;
889     app.add_option("--str", str);
890 
891     args = {"--str"};
892 
893     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
894 }
895 
896 TEST_CASE_METHOD(TApp, "NotRequiredOptsSingleShort", "[app]") {
897 
898     std::string str;
899     app.add_option("-s", str);
900 
901     args = {"-s"};
902 
903     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
904 }
905 
906 TEST_CASE_METHOD(TApp, "RequiredOptsSingle", "[app]") {
907 
908     std::string str;
909     app.add_option("--str", str)->required();
910 
911     args = {"--str"};
912 
913     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
914 }
915 
916 TEST_CASE_METHOD(TApp, "RequiredOptsSingleShort", "[app]") {
917 
918     std::string str;
919     app.add_option("-s", str)->required();
920 
921     args = {"-s"};
922 
923     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
924 }
925 
926 TEST_CASE_METHOD(TApp, "RequiredOptsDouble", "[app]") {
927 
928     std::vector<std::string> strs;
929     app.add_option("--str", strs)->required()->expected(2);
930 
931     args = {"--str", "one"};
932 
933     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
934 
935     args = {"--str", "one", "two"};
936 
937     run();
938 
939     CHECK(std::vector<std::string>({"one", "two"}) == strs);
940 }
941 
942 TEST_CASE_METHOD(TApp, "RequiredOptsDoubleShort", "[app]") {
943 
944     std::vector<std::string> strs;
945     app.add_option("-s", strs)->required()->expected(2);
946 
947     args = {"-s", "one"};
948 
949     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
950 
951     args = {"-s", "one", "-s", "one", "-s", "one"};
952 
953     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
954 }
955 
956 TEST_CASE_METHOD(TApp, "RequiredOptsDoubleNeg", "[app]") {
957     std::vector<std::string> strs;
958     app.add_option("-s", strs)->required()->expected(-2);
959 
960     args = {"-s", "one"};
961 
962     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
963 
964     args = {"-s", "one", "two", "-s", "three"};
965 
966     REQUIRE_NOTHROW(run());
967     CHECK(std::vector<std::string>({"one", "two", "three"}) == strs);
968 
969     args = {"-s", "one", "two"};
970     REQUIRE_NOTHROW(run());
971     CHECK(std::vector<std::string>({"one", "two"}) == strs);
972 }
973 
974 // This makes sure unlimited option priority is
975 // correct for space vs. no space #90
976 TEST_CASE_METHOD(TApp, "PositionalNoSpace", "[app]") {
977     std::vector<std::string> options;
978     std::string foo, bar;
979 
980     app.add_option("-O", options);
981     app.add_option("foo", foo)->required();
982     app.add_option("bar", bar)->required();
983 
984     args = {"-O", "Test", "param1", "param2"};
985     run();
986 
987     CHECK(1u == options.size());
988     CHECK("Test" == options.at(0));
989 
990     args = {"-OTest", "param1", "param2"};
991     run();
992 
993     CHECK(1u == options.size());
994     CHECK("Test" == options.at(0));
995 }
996 
997 // Tests positionals at end
998 TEST_CASE_METHOD(TApp, "PositionalAtEnd", "[app]") {
999     std::string options;
1000     std::string foo;
1001 
1002     app.add_option("-O", options);
1003     app.add_option("foo", foo);
1004     app.positionals_at_end();
1005     CHECK(app.get_positionals_at_end());
1006     args = {"-O", "Test", "param1"};
1007     run();
1008 
1009     CHECK("Test" == options);
1010     CHECK("param1" == foo);
1011 
1012     args = {"param2", "-O", "Test"};
1013     CHECK_THROWS_AS(run(), CLI::ExtrasError);
1014 }
1015 
1016 // Tests positionals at end
1017 TEST_CASE_METHOD(TApp, "RequiredPositionals", "[app]") {
1018     std::vector<std::string> sources;
1019     std::string dest;
1020     app.add_option("src", sources);
1021     app.add_option("dest", dest)->required();
1022     app.positionals_at_end();
1023 
1024     args = {"1", "2", "3"};
1025     run();
1026 
1027     CHECK(2u == sources.size());
1028     CHECK("3" == dest);
1029 
1030     args = {"a"};
1031     sources.clear();
1032     run();
1033 
1034     CHECK(0u == sources.size());
1035     CHECK("a" == dest);
1036 }
1037 
1038 TEST_CASE_METHOD(TApp, "RequiredPositionalVector", "[app]") {
1039     std::string d1;
1040     std::string d2;
1041     std::string d3;
1042     std::vector<std::string> sources;
1043 
1044     app.add_option("dest1", d1);
1045     app.add_option("dest2", d2);
1046     app.add_option("dest3", d3);
1047     app.add_option("src", sources)->required();
1048 
1049     app.positionals_at_end();
1050 
1051     args = {"1", "2", "3"};
1052     run();
1053 
1054     CHECK(1u == sources.size());
1055     CHECK("1" == d1);
1056     CHECK("2" == d2);
1057     CHECK(d3.empty());
1058     args = {"a"};
1059     sources.clear();
1060     run();
1061 
1062     CHECK(1u == sources.size());
1063 }
1064 
1065 // Tests positionals at end
1066 TEST_CASE_METHOD(TApp, "RequiredPositionalValidation", "[app]") {
1067     std::vector<std::string> sources;
1068     int dest;  // required
1069     std::string d2;
1070     app.add_option("src", sources);
1071     app.add_option("dest", dest)->required()->check(CLI::PositiveNumber);
1072     app.add_option("dest2", d2)->required();
1073     app.positionals_at_end()->validate_positionals();
1074 
1075     args = {"1", "2", "string", "3"};
1076     run();
1077 
1078     CHECK(2u == sources.size());
1079     CHECK(3 == dest);
1080     CHECK("string" == d2);
1081 }
1082 
1083 // Tests positionals at end
1084 TEST_CASE_METHOD(TApp, "PositionalValidation", "[app]") {
1085     std::string options;
1086     std::string foo;
1087 
1088     app.add_option("bar", options)->check(CLI::Number.name("valbar"));
1089     // disable the check on foo
1090     app.add_option("foo", foo)->check(CLI::Number.active(false));
1091     app.validate_positionals();
1092     args = {"1", "param1"};
1093     run();
1094 
1095     CHECK("1" == options);
1096     CHECK("param1" == foo);
1097 
1098     args = {"param1", "1"};
1099     CHECK_NOTHROW(run());
1100 
1101     CHECK("1" == options);
1102     CHECK("param1" == foo);
1103 
1104     CHECK(nullptr != app.get_option("bar")->get_validator("valbar"));
1105 }
1106 
1107 TEST_CASE_METHOD(TApp, "PositionalNoSpaceLong", "[app]") {
1108     std::vector<std::string> options;
1109     std::string foo, bar;
1110 
1111     app.add_option("--option", options);
1112     app.add_option("foo", foo)->required();
1113     app.add_option("bar", bar)->required();
1114 
1115     args = {"--option", "Test", "param1", "param2"};
1116     run();
1117 
1118     CHECK(1u == options.size());
1119     CHECK("Test" == options.at(0));
1120 
1121     args = {"--option=Test", "param1", "param2"};
1122     run();
1123 
1124     CHECK(1u == options.size());
1125     CHECK("Test" == options.at(0));
1126 }
1127 
1128 TEST_CASE_METHOD(TApp, "RequiredOptsUnlimited", "[app]") {
1129 
1130     std::vector<std::string> strs;
1131     app.add_option("--str", strs)->required();
1132 
1133     args = {"--str"};
1134     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
1135 
1136     args = {"--str", "one", "--str", "two"};
1137     run();
1138     CHECK(std::vector<std::string>({"one", "two"}) == strs);
1139 
1140     args = {"--str", "one", "two"};
1141     run();
1142     CHECK(std::vector<std::string>({"one", "two"}) == strs);
1143 
1144     // It's better to feed a hungry option than to feed allow_extras
1145     app.allow_extras();
1146     run();
1147     CHECK(std::vector<std::string>({"one", "two"}) == strs);
1148     CHECK(std::vector<std::string>({}) == app.remaining());
1149 
1150     app.allow_extras(false);
1151     std::vector<std::string> remain;
1152     auto popt = app.add_option("positional", remain);
1153     run();
1154     CHECK(std::vector<std::string>({"one", "two"}) == strs);
1155     CHECK(std::vector<std::string>() == remain);
1156 
1157     args = {"--str", "one", "--", "two"};
1158 
1159     run();
1160     CHECK(std::vector<std::string>({"one"}) == strs);
1161     CHECK(std::vector<std::string>({"two"}) == remain);
1162 
1163     args = {"one", "--str", "two"};
1164 
1165     run();
1166     CHECK(std::vector<std::string>({"two"}) == strs);
1167     CHECK(std::vector<std::string>({"one"}) == remain);
1168 
1169     args = {"--str", "one", "two"};
1170     popt->required();
1171     run();
1172     CHECK(std::vector<std::string>({"one"}) == strs);
1173     CHECK(std::vector<std::string>({"two"}) == remain);
1174 }
1175 
1176 TEST_CASE_METHOD(TApp, "RequiredOptsUnlimitedShort", "[app]") {
1177 
1178     std::vector<std::string> strs;
1179     app.add_option("-s", strs)->required();
1180 
1181     args = {"-s"};
1182     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
1183 
1184     args = {"-s", "one", "-s", "two"};
1185     run();
1186     CHECK(std::vector<std::string>({"one", "two"}) == strs);
1187 
1188     args = {"-s", "one", "two"};
1189     run();
1190     CHECK(std::vector<std::string>({"one", "two"}) == strs);
1191 
1192     // It's better to feed a hungry option than to feed allow_extras
1193     app.allow_extras();
1194     run();
1195     CHECK(std::vector<std::string>({"one", "two"}) == strs);
1196     CHECK(std::vector<std::string>({}) == app.remaining());
1197 
1198     app.allow_extras(false);
1199     std::vector<std::string> remain;
1200     app.add_option("positional", remain);
1201     run();
1202     CHECK(std::vector<std::string>({"one", "two"}) == strs);
1203     CHECK(std::vector<std::string>() == remain);
1204 
1205     args = {"-s", "one", "--", "two"};
1206 
1207     run();
1208     CHECK(std::vector<std::string>({"one"}) == strs);
1209     CHECK(std::vector<std::string>({"two"}) == remain);
1210 
1211     args = {"one", "-s", "two"};
1212 
1213     run();
1214     CHECK(std::vector<std::string>({"two"}) == strs);
1215     CHECK(std::vector<std::string>({"one"}) == remain);
1216 }
1217 
1218 TEST_CASE_METHOD(TApp, "OptsUnlimitedEnd", "[app]") {
1219     std::vector<std::string> strs;
1220     app.add_option("-s,--str", strs);
1221     app.allow_extras();
1222 
1223     args = {"one", "-s", "two", "three", "--", "four"};
1224 
1225     run();
1226 
1227     CHECK(std::vector<std::string>({"two", "three"}) == strs);
1228     CHECK(std::vector<std::string>({"one", "four"}) == app.remaining());
1229 }
1230 
1231 TEST_CASE_METHOD(TApp, "RequireOptPriority", "[app]") {
1232 
1233     std::vector<std::string> strs;
1234     app.add_option("--str", strs);
1235     std::vector<std::string> remain;
1236     app.add_option("positional", remain)->expected(2)->required();
1237 
1238     args = {"--str", "one", "two", "three"};
1239     run();
1240 
1241     CHECK(std::vector<std::string>({"one"}) == strs);
1242     CHECK(std::vector<std::string>({"two", "three"}) == remain);
1243 
1244     args = {"two", "three", "--str", "one", "four"};
1245     run();
1246 
1247     CHECK(std::vector<std::string>({"one", "four"}) == strs);
1248     CHECK(std::vector<std::string>({"two", "three"}) == remain);
1249 }
1250 
1251 TEST_CASE_METHOD(TApp, "RequireOptPriorityShort", "[app]") {
1252 
1253     std::vector<std::string> strs;
1254     app.add_option("-s", strs)->required();
1255     std::vector<std::string> remain;
1256     app.add_option("positional", remain)->expected(2)->required();
1257 
1258     args = {"-s", "one", "two", "three"};
1259     run();
1260 
1261     CHECK(std::vector<std::string>({"one"}) == strs);
1262     CHECK(std::vector<std::string>({"two", "three"}) == remain);
1263 
1264     args = {"two", "three", "-s", "one", "four"};
1265     run();
1266 
1267     CHECK(std::vector<std::string>({"one", "four"}) == strs);
1268     CHECK(std::vector<std::string>({"two", "three"}) == remain);
1269 }
1270 
1271 TEST_CASE_METHOD(TApp, "NotRequiredExpectedDouble", "[app]") {
1272 
1273     std::vector<std::string> strs;
1274     app.add_option("--str", strs)->expected(2);
1275 
1276     args = {"--str", "one"};
1277 
1278     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
1279 }
1280 
1281 TEST_CASE_METHOD(TApp, "NotRequiredExpectedDoubleShort", "[app]") {
1282 
1283     std::vector<std::string> strs;
1284     app.add_option("-s", strs)->expected(2);
1285 
1286     args = {"-s", "one"};
1287 
1288     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
1289 }
1290 
1291 TEST_CASE_METHOD(TApp, "RequiredFlags", "[app]") {
1292     app.add_flag("-a")->required();
1293     app.add_flag("-b")->mandatory();  // Alternate term
1294 
1295     CHECK_THROWS_AS(run(), CLI::RequiredError);
1296 
1297     args = {"-a"};
1298     CHECK_THROWS_AS(run(), CLI::RequiredError);
1299 
1300     args = {"-b"};
1301     CHECK_THROWS_AS(run(), CLI::RequiredError);
1302 
1303     args = {"-a", "-b"};
1304     run();
1305 }
1306 
1307 TEST_CASE_METHOD(TApp, "CallbackFlags", "[app]") {
1308 
1309     std::int64_t value{0};
1310 
__anon9f71efcd0102(std::int64_t x) 1311     auto func = [&value](std::int64_t x) { value = x; };
1312 
1313     app.add_flag_function("-v", func);
1314 
1315     run();
1316     CHECK(0u == value);
1317 
1318     args = {"-v"};
1319     run();
1320     CHECK(1u == value);
1321 
1322     args = {"-vv"};
1323     run();
1324     CHECK(2u == value);
1325 
1326     CHECK_THROWS_AS(app.add_flag_function("hi", func), CLI::IncorrectConstruction);
1327 }
1328 
1329 TEST_CASE_METHOD(TApp, "CallbackFlagsFalse", "[app]") {
1330     std::int64_t value = 0;
1331 
__anon9f71efcd0202(std::int64_t x) 1332     auto func = [&value](std::int64_t x) { value = x; };
1333 
1334     app.add_flag_function("-v,-f{false},--val,--fval{false}", func);
1335 
1336     run();
1337     CHECK(0 == value);
1338 
1339     args = {"-f"};
1340     run();
1341     CHECK(-1 == value);
1342 
1343     args = {"-vfv"};
1344     run();
1345     CHECK(1 == value);
1346 
1347     args = {"--fval"};
1348     run();
1349     CHECK(-1 == value);
1350 
1351     args = {"--fval=2"};
1352     run();
1353     CHECK(-2 == value);
1354 
1355     CHECK_THROWS_AS(app.add_flag_function("hi", func), CLI::IncorrectConstruction);
1356 }
1357 
1358 TEST_CASE_METHOD(TApp, "CallbackFlagsFalseShortcut", "[app]") {
1359     std::int64_t value = 0;
1360 
__anon9f71efcd0302(std::int64_t x) 1361     auto func = [&value](std::int64_t x) { value = x; };
1362 
1363     app.add_flag_function("-v,!-f,--val,!--fval", func);
1364 
1365     run();
1366     CHECK(0 == value);
1367 
1368     args = {"-f"};
1369     run();
1370     CHECK(-1 == value);
1371 
1372     args = {"-vfv"};
1373     run();
1374     CHECK(1 == value);
1375 
1376     args = {"--fval"};
1377     run();
1378     CHECK(-1 == value);
1379 
1380     args = {"--fval=2"};
1381     run();
1382     CHECK(-2 == value);
1383 
1384     CHECK_THROWS_AS(app.add_flag_function("hi", func), CLI::IncorrectConstruction);
1385 }
1386 
1387 #if __cplusplus >= 201402L || _MSC_VER >= 1900
1388 TEST_CASE_METHOD(TApp, "CallbackFlagsAuto", "[app]") {
1389 
1390     std::int64_t value{0};
1391 
__anon9f71efcd0402(std::int64_t x) 1392     auto func = [&value](std::int64_t x) { value = x; };
1393 
1394     app.add_flag("-v", func);
1395 
1396     run();
1397     CHECK(0u == value);
1398 
1399     args = {"-v"};
1400     run();
1401     CHECK(1u == value);
1402 
1403     args = {"-vv"};
1404     run();
1405     CHECK(2u == value);
1406 
1407     CHECK_THROWS_AS(app.add_flag("hi", func), CLI::IncorrectConstruction);
1408 }
1409 #endif
1410 
1411 TEST_CASE_METHOD(TApp, "Positionals", "[app]") {
1412 
1413     std::string posit1;
1414     std::string posit2;
1415     app.add_option("posit1", posit1);
1416     app.add_option("posit2", posit2);
1417 
1418     args = {"thing1", "thing2"};
1419 
1420     run();
1421 
1422     CHECK(app.count("posit1") == 1u);
1423     CHECK(app.count("posit2") == 1u);
1424     CHECK(posit1 == "thing1");
1425     CHECK(posit2 == "thing2");
1426 }
1427 
1428 TEST_CASE_METHOD(TApp, "ForcedPositional", "[app]") {
1429     std::vector<std::string> posit;
1430     auto one = app.add_flag("--one");
1431     app.add_option("posit", posit);
1432 
1433     args = {"--one", "two", "three"};
1434     run();
1435     std::vector<std::string> answers1 = {"two", "three"};
1436     CHECK(one->count());
1437     CHECK(posit == answers1);
1438 
1439     args = {"--", "--one", "two", "three"};
1440     std::vector<std::string> answers2 = {"--one", "two", "three"};
1441     run();
1442 
1443     CHECK(!one->count());
1444     CHECK(posit == answers2);
1445 }
1446 
1447 TEST_CASE_METHOD(TApp, "MixedPositionals", "[app]") {
1448 
1449     int positional_int{0};
1450     std::string positional_string;
1451     app.add_option("posit1,--posit1", positional_int, "");
1452     app.add_option("posit2,--posit2", positional_string, "");
1453 
1454     args = {"--posit2", "thing2", "7"};
1455 
1456     run();
1457 
1458     CHECK(app.count("posit2") == 1u);
1459     CHECK(app.count("--posit1") == 1u);
1460     CHECK(positional_int == 7);
1461     CHECK(positional_string == "thing2");
1462 }
1463 
1464 TEST_CASE_METHOD(TApp, "BigPositional", "[app]") {
1465     std::vector<std::string> vec;
1466     app.add_option("pos", vec);
1467 
1468     args = {"one"};
1469 
1470     run();
1471     CHECK(vec == args);
1472 
1473     args = {"one", "two"};
1474     run();
1475 
1476     CHECK(vec == args);
1477 }
1478 
1479 TEST_CASE_METHOD(TApp, "Reset", "[app]") {
1480 
1481     app.add_flag("--simple");
1482     double doub{0.0};
1483     app.add_option("-d,--double", doub);
1484 
1485     args = {"--simple", "--double", "1.2"};
1486 
1487     run();
1488 
1489     CHECK(app.count("--simple") == 1u);
1490     CHECK(app.count("-d") == 1u);
1491     CHECK(doub == Approx(1.2));
1492 
1493     app.clear();
1494 
1495     CHECK(app.count("--simple") == 0u);
1496     CHECK(app.count("-d") == 0u);
1497 
1498     run();
1499 
1500     CHECK(app.count("--simple") == 1u);
1501     CHECK(app.count("-d") == 1u);
1502     CHECK(doub == Approx(1.2));
1503 }
1504 
1505 TEST_CASE_METHOD(TApp, "RemoveOption", "[app]") {
1506     app.add_flag("--one");
1507     auto opt = app.add_flag("--two");
1508 
1509     CHECK(app.remove_option(opt));
1510     CHECK(!app.remove_option(opt));
1511 
1512     args = {"--two"};
1513 
1514     CHECK_THROWS_AS(run(), CLI::ExtrasError);
1515 }
1516 
1517 TEST_CASE_METHOD(TApp, "RemoveNeedsLinks", "[app]") {
1518     auto one = app.add_flag("--one");
1519     auto two = app.add_flag("--two");
1520 
1521     two->needs(one);
1522     one->needs(two);
1523 
1524     CHECK(app.remove_option(one));
1525 
1526     args = {"--two"};
1527 
1528     run();
1529 }
1530 
1531 TEST_CASE_METHOD(TApp, "RemoveExcludesLinks", "[app]") {
1532     auto one = app.add_flag("--one");
1533     auto two = app.add_flag("--two");
1534 
1535     two->excludes(one);
1536     one->excludes(two);
1537 
1538     CHECK(app.remove_option(one));
1539 
1540     args = {"--two"};
1541 
1542     run();  // Mostly hoping it does not crash
1543 }
1544 
1545 TEST_CASE_METHOD(TApp, "FileNotExists", "[app]") {
1546     std::string myfile{"TestNonFileNotUsed.txt"};
1547     REQUIRE_NOTHROW(CLI::NonexistentPath(myfile));
1548 
1549     std::string filename;
1550     auto opt = app.add_option("--file", filename)->check(CLI::NonexistentPath, "path_check");
1551     args = {"--file", myfile};
1552 
1553     run();
1554     CHECK(filename == myfile);
1555 
1556     bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a'));  // create file
1557     CHECK(ok);
1558     CHECK_THROWS_AS(run(), CLI::ValidationError);
1559     // deactivate the check, so it should run now
1560     opt->get_validator("path_check")->active(false);
1561     CHECK_NOTHROW(run());
1562     std::remove(myfile.c_str());
1563     CHECK(!CLI::ExistingFile(myfile).empty());
1564 }
1565 
1566 TEST_CASE_METHOD(TApp, "FileExists", "[app]") {
1567     std::string myfile{"TestNonFileNotUsed.txt"};
1568     CHECK(!CLI::ExistingFile(myfile).empty());
1569 
1570     std::string filename = "Failed";
1571     app.add_option("--file", filename)->check(CLI::ExistingFile);
1572     args = {"--file", myfile};
1573 
1574     CHECK_THROWS_AS(run(), CLI::ValidationError);
1575 
1576     bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a'));  // create file
1577     CHECK(ok);
1578     run();
1579     CHECK(filename == myfile);
1580 
1581     std::remove(myfile.c_str());
1582     CHECK(!CLI::ExistingFile(myfile).empty());
1583 }
1584 
1585 TEST_CASE_METHOD(TApp, "NotFileExists", "[app]") {
1586     std::string myfile{"TestNonFileNotUsed.txt"};
1587     CHECK(!CLI::ExistingFile(myfile).empty());
1588 
1589     std::string filename = "Failed";
1590     app.add_option("--file", filename)->check(!CLI::ExistingFile);
1591     args = {"--file", myfile};
1592 
1593     CHECK_NOTHROW(run());
1594 
1595     bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a'));  // create file
1596     CHECK(ok);
1597     CHECK_THROWS_AS(run(), CLI::ValidationError);
1598 
1599     std::remove(myfile.c_str());
1600     CHECK(!CLI::ExistingFile(myfile).empty());
1601 }
1602 
1603 TEST_CASE_METHOD(TApp, "DefaultedResult", "[app]") {
1604     std::string sval = "NA";
1605     int ival{0};
1606     auto opts = app.add_option("--string", sval)->capture_default_str();
1607     auto optv = app.add_option("--val", ival);
1608     args = {};
1609     run();
1610     CHECK("NA" == sval);
1611     std::string nString;
1612     opts->results(nString);
1613     CHECK("NA" == nString);
1614     int newIval;
1615     // CHECK_THROWS_AS (optv->results(newIval), CLI::ConversionError);
1616     optv->default_str("442");
1617     optv->results(newIval);
1618     CHECK(442 == newIval);
1619 }
1620 
1621 TEST_CASE_METHOD(TApp, "OriginalOrder", "[app]") {
1622     std::vector<int> st1;
1623     CLI::Option *op1 = app.add_option("-a", st1);
1624     std::vector<int> st2;
1625     CLI::Option *op2 = app.add_option("-b", st2);
1626 
1627     args = {"-a", "1", "-b", "2", "-a3", "-a", "4"};
1628 
1629     run();
1630 
1631     CHECK(std::vector<int>({1, 3, 4}) == st1);
1632     CHECK(std::vector<int>({2}) == st2);
1633 
1634     CHECK(std::vector<CLI::Option *>({op1, op2, op1, op1}) == app.parse_order());
1635 }
1636 
1637 TEST_CASE_METHOD(TApp, "NeedsFlags", "[app]") {
1638     CLI::Option *opt = app.add_flag("-s,--string");
1639     app.add_flag("--both")->needs(opt);
1640 
1641     run();
1642 
1643     args = {"-s"};
1644     run();
1645 
1646     args = {"-s", "--both"};
1647     run();
1648 
1649     args = {"--both"};
1650     CHECK_THROWS_AS(run(), CLI::RequiresError);
1651 
1652     CHECK_NOTHROW(opt->needs(opt));
1653 }
1654 
1655 TEST_CASE_METHOD(TApp, "ExcludesFlags", "[app]") {
1656     CLI::Option *opt = app.add_flag("-s,--string");
1657     app.add_flag("--nostr")->excludes(opt);
1658 
1659     run();
1660 
1661     args = {"-s"};
1662     run();
1663 
1664     args = {"--nostr"};
1665     run();
1666 
1667     args = {"--nostr", "-s"};
1668     CHECK_THROWS_AS(run(), CLI::ExcludesError);
1669 
1670     args = {"--string", "--nostr"};
1671     CHECK_THROWS_AS(run(), CLI::ExcludesError);
1672 
1673     CHECK_THROWS_AS(opt->excludes(opt), CLI::IncorrectConstruction);
1674 }
1675 
1676 TEST_CASE_METHOD(TApp, "ExcludesMixedFlags", "[app]") {
1677     CLI::Option *opt1 = app.add_flag("--opt1");
1678     app.add_flag("--opt2");
1679     CLI::Option *opt3 = app.add_flag("--opt3");
1680     app.add_flag("--no")->excludes(opt1, "--opt2", opt3);
1681 
1682     run();
1683 
1684     args = {"--no"};
1685     run();
1686 
1687     args = {"--opt2"};
1688     run();
1689 
1690     args = {"--no", "--opt1"};
1691     CHECK_THROWS_AS(run(), CLI::ExcludesError);
1692 
1693     args = {"--no", "--opt2"};
1694     CHECK_THROWS_AS(run(), CLI::ExcludesError);
1695 }
1696 
1697 TEST_CASE_METHOD(TApp, "NeedsMultiFlags", "[app]") {
1698     CLI::Option *opt1 = app.add_flag("--opt1");
1699     CLI::Option *opt2 = app.add_flag("--opt2");
1700     CLI::Option *opt3 = app.add_flag("--opt3");
1701     app.add_flag("--optall")->needs(opt1, opt2, opt3);
1702 
1703     run();
1704 
1705     args = {"--opt1"};
1706     run();
1707 
1708     args = {"--opt2"};
1709     run();
1710 
1711     args = {"--optall"};
1712     CHECK_THROWS_AS(run(), CLI::RequiresError);
1713 
1714     args = {"--optall", "--opt1"};
1715     CHECK_THROWS_AS(run(), CLI::RequiresError);
1716 
1717     args = {"--optall", "--opt2", "--opt1"};
1718     CHECK_THROWS_AS(run(), CLI::RequiresError);
1719 
1720     args = {"--optall", "--opt1", "--opt2", "--opt3"};
1721     run();
1722 }
1723 
1724 TEST_CASE_METHOD(TApp, "NeedsMixedFlags", "[app]") {
1725     CLI::Option *opt1 = app.add_flag("--opt1");
1726     app.add_flag("--opt2");
1727     app.add_flag("--opt3");
1728     app.add_flag("--optall")->needs(opt1, "--opt2", "--opt3");
1729 
1730     run();
1731 
1732     args = {"--opt1"};
1733     run();
1734 
1735     args = {"--opt2"};
1736     run();
1737 
1738     args = {"--optall"};
1739     CHECK_THROWS_AS(run(), CLI::RequiresError);
1740 
1741     args = {"--optall", "--opt1"};
1742     CHECK_THROWS_AS(run(), CLI::RequiresError);
1743 
1744     args = {"--optall", "--opt2", "--opt1"};
1745     CHECK_THROWS_AS(run(), CLI::RequiresError);
1746 
1747     args = {"--optall", "--opt1", "--opt2", "--opt3"};
1748     run();
1749 }
1750 
1751 TEST_CASE_METHOD(TApp, "NeedsChainedFlags", "[app]") {
1752     CLI::Option *opt1 = app.add_flag("--opt1");
1753     CLI::Option *opt2 = app.add_flag("--opt2")->needs(opt1);
1754     app.add_flag("--opt3")->needs(opt2);
1755 
1756     run();
1757 
1758     args = {"--opt1"};
1759     run();
1760 
1761     args = {"--opt2"};
1762     CHECK_THROWS_AS(run(), CLI::RequiresError);
1763 
1764     args = {"--opt3"};
1765     CHECK_THROWS_AS(run(), CLI::RequiresError);
1766 
1767     args = {"--opt3", "--opt2"};
1768     CHECK_THROWS_AS(run(), CLI::RequiresError);
1769 
1770     args = {"--opt3", "--opt1"};
1771     CHECK_THROWS_AS(run(), CLI::RequiresError);
1772 
1773     args = {"--opt2", "--opt1"};
1774     run();
1775 
1776     args = {"--opt1", "--opt2", "--opt3"};
1777     run();
1778 }
1779 
1780 TEST_CASE_METHOD(TApp, "Env", "[app]") {
1781 
1782     put_env("CLI11_TEST_ENV_TMP", "2");
1783 
1784     int val{1};
1785     CLI::Option *vopt = app.add_option("--tmp", val)->envname("CLI11_TEST_ENV_TMP");
1786 
1787     run();
1788 
1789     CHECK(val == 2);
1790     CHECK(vopt->count() == 1u);
1791 
1792     vopt->required();
1793     run();
1794 
1795     unset_env("CLI11_TEST_ENV_TMP");
1796     CHECK_THROWS_AS(run(), CLI::RequiredError);
1797 }
1798 
1799 // curiously check if an environmental only option works
1800 TEST_CASE_METHOD(TApp, "EnvOnly", "[app]") {
1801 
1802     put_env("CLI11_TEST_ENV_TMP", "2");
1803 
1804     int val{1};
1805     CLI::Option *vopt = app.add_option("", val)->envname("CLI11_TEST_ENV_TMP");
1806 
1807     run();
1808 
1809     CHECK(val == 2);
1810     CHECK(vopt->count() == 1u);
1811 
1812     vopt->required();
1813     run();
1814 
1815     unset_env("CLI11_TEST_ENV_TMP");
1816     CHECK_THROWS_AS(run(), CLI::RequiredError);
1817 }
1818 
1819 TEST_CASE_METHOD(TApp, "RangeInt", "[app]") {
1820     int x{0};
1821     app.add_option("--one", x)->check(CLI::Range(3, 6));
1822 
1823     args = {"--one=1"};
1824     CHECK_THROWS_AS(run(), CLI::ValidationError);
1825 
1826     args = {"--one=7"};
1827     CHECK_THROWS_AS(run(), CLI::ValidationError);
1828 
1829     args = {"--one=3"};
1830     run();
1831 
1832     args = {"--one=5"};
1833     run();
1834 
1835     args = {"--one=6"};
1836     run();
1837 }
1838 
1839 TEST_CASE_METHOD(TApp, "RangeDouble", "[app]") {
1840 
1841     double x{0.0};
1842     /// Note that this must be a double in Range, too
1843     app.add_option("--one", x)->check(CLI::Range(3.0, 6.0));
1844 
1845     args = {"--one=1"};
1846     CHECK_THROWS_AS(run(), CLI::ValidationError);
1847 
1848     args = {"--one=7"};
1849     CHECK_THROWS_AS(run(), CLI::ValidationError);
1850 
1851     args = {"--one=3"};
1852     run();
1853 
1854     args = {"--one=5"};
1855     run();
1856 
1857     args = {"--one=6"};
1858     run();
1859 }
1860 
1861 TEST_CASE_METHOD(TApp, "typeCheck", "[app]") {
1862 
1863     /// Note that this must be a double in Range, too
1864     app.add_option("--one")->check(CLI::TypeValidator<unsigned int>());
1865 
1866     args = {"--one=1"};
1867     CHECK_NOTHROW(run());
1868 
1869     args = {"--one=-7"};
1870     CHECK_THROWS_AS(run(), CLI::ValidationError);
1871 
1872     args = {"--one=error"};
1873     CHECK_THROWS_AS(run(), CLI::ValidationError);
1874 
1875     args = {"--one=4.568"};
1876     CHECK_THROWS_AS(run(), CLI::ValidationError);
1877 }
1878 
1879 // Check to make sure programmatic access to left over is available
1880 TEST_CASE_METHOD(TApp, "AllowExtras", "[app]") {
1881 
1882     app.allow_extras();
1883 
1884     bool val{true};
1885     app.add_flag("-f", val);
1886 
1887     args = {"-x", "-f"};
1888 
1889     REQUIRE_NOTHROW(run());
1890     CHECK(val);
1891     CHECK(std::vector<std::string>({"-x"}) == app.remaining());
1892 }
1893 
1894 TEST_CASE_METHOD(TApp, "AllowExtrasOrder", "[app]") {
1895 
1896     app.allow_extras();
1897 
1898     args = {"-x", "-f"};
1899     REQUIRE_NOTHROW(run());
1900     CHECK(std::vector<std::string>({"-x", "-f"}) == app.remaining());
1901 
1902     std::vector<std::string> left_over = app.remaining();
1903     app.parse(left_over);
1904     CHECK(std::vector<std::string>({"-f", "-x"}) == app.remaining());
1905     CHECK(left_over == app.remaining_for_passthrough());
1906 }
1907 
1908 TEST_CASE_METHOD(TApp, "AllowExtrasCascade", "[app]") {
1909 
1910     app.allow_extras();
1911 
1912     args = {"-x", "45", "-f", "27"};
1913     REQUIRE_NOTHROW(run());
1914     CHECK(std::vector<std::string>({"-x", "45", "-f", "27"}) == app.remaining());
1915 
1916     std::vector<std::string> left_over = app.remaining_for_passthrough();
1917 
1918     CLI::App capp{"cascade_program"};
1919     int v1 = 0;
1920     int v2 = 0;
1921     capp.add_option("-x", v1);
1922     capp.add_option("-f", v2);
1923 
1924     capp.parse(left_over);
1925     CHECK(45 == v1);
1926     CHECK(27 == v2);
1927 }
1928 // makes sure the error throws on the rValue version of the parse
1929 TEST_CASE_METHOD(TApp, "ExtrasErrorRvalueParse", "[app]") {
1930 
1931     args = {"-x", "45", "-f", "27"};
1932     CHECK_THROWS_AS(app.parse(std::vector<std::string>({"-x", "45", "-f", "27"})), CLI::ExtrasError);
1933 }
1934 
1935 TEST_CASE_METHOD(TApp, "AllowExtrasCascadeDirect", "[app]") {
1936 
1937     app.allow_extras();
1938 
1939     args = {"-x", "45", "-f", "27"};
1940     REQUIRE_NOTHROW(run());
1941     CHECK(std::vector<std::string>({"-x", "45", "-f", "27"}) == app.remaining());
1942 
1943     CLI::App capp{"cascade_program"};
1944     int v1{0};
1945     int v2{0};
1946     capp.add_option("-x", v1);
1947     capp.add_option("-f", v2);
1948 
1949     capp.parse(app.remaining_for_passthrough());
1950     CHECK(45 == v1);
1951     CHECK(27 == v2);
1952 }
1953 
1954 TEST_CASE_METHOD(TApp, "AllowExtrasArgModify", "[app]") {
1955 
1956     int v1{0};
1957     int v2{0};
1958     app.allow_extras();
1959     app.add_option("-f", v2);
1960     args = {"27", "-f", "45", "-x"};
1961     app.parse(args);
1962     CHECK(std::vector<std::string>({"45", "-x"}) == args);
1963 
1964     CLI::App capp{"cascade_program"};
1965 
1966     capp.add_option("-x", v1);
1967 
1968     capp.parse(args);
1969     CHECK(45 == v1);
1970     CHECK(27 == v2);
1971 }
1972 
1973 // Test horrible error
1974 TEST_CASE_METHOD(TApp, "CheckShortFail", "[app]") {
1975     args = {"--two"};
1976 
1977     CHECK_THROWS_AS(CLI::detail::AppFriend::parse_arg(&app, args, CLI::detail::Classifier::SHORT), CLI::HorribleError);
1978 }
1979 
1980 // Test horrible error
1981 TEST_CASE_METHOD(TApp, "CheckLongFail", "[app]") {
1982     args = {"-t"};
1983 
1984     CHECK_THROWS_AS(CLI::detail::AppFriend::parse_arg(&app, args, CLI::detail::Classifier::LONG), CLI::HorribleError);
1985 }
1986 
1987 // Test horrible error
1988 TEST_CASE_METHOD(TApp, "CheckWindowsFail", "[app]") {
1989     args = {"-t"};
1990 
1991     CHECK_THROWS_AS(CLI::detail::AppFriend::parse_arg(&app, args, CLI::detail::Classifier::WINDOWS_STYLE),
1992                     CLI::HorribleError);
1993 }
1994 
1995 // Test horrible error
1996 TEST_CASE_METHOD(TApp, "CheckOtherFail", "[app]") {
1997     args = {"-t"};
1998 
1999     CHECK_THROWS_AS(CLI::detail::AppFriend::parse_arg(&app, args, CLI::detail::Classifier::NONE), CLI::HorribleError);
2000 }
2001 
2002 // Test horrible error
2003 TEST_CASE_METHOD(TApp, "CheckSubcomFail", "[app]") {
2004     args = {"subcom"};
2005 
2006     CHECK_THROWS_AS(CLI::detail::AppFriend::parse_subcommand(&app, args), CLI::HorribleError);
2007 }
2008 
2009 TEST_CASE_METHOD(TApp, "FallthroughParentFail", "[app]") {
2010     CHECK_THROWS_AS(CLI::detail::AppFriend::get_fallthrough_parent(&app), CLI::HorribleError);
2011 }
2012 
2013 TEST_CASE_METHOD(TApp, "FallthroughParents", "[app]") {
2014     auto sub = app.add_subcommand("test");
2015     CHECK(&app == CLI::detail::AppFriend::get_fallthrough_parent(sub));
2016 
2017     auto ssub = sub->add_subcommand("sub2");
2018     CHECK(sub == CLI::detail::AppFriend::get_fallthrough_parent(ssub));
2019 
2020     auto og1 = app.add_option_group("g1");
2021     auto og2 = og1->add_option_group("g2");
2022     auto og3 = og2->add_option_group("g3");
2023     CHECK(&app == CLI::detail::AppFriend::get_fallthrough_parent(og3));
2024 
2025     auto ogb1 = sub->add_option_group("g1");
2026     auto ogb2 = ogb1->add_option_group("g2");
2027     auto ogb3 = ogb2->add_option_group("g3");
2028     CHECK(sub == CLI::detail::AppFriend::get_fallthrough_parent(ogb3));
2029 
2030     ogb2->name("groupb");
2031     CHECK(ogb2 == CLI::detail::AppFriend::get_fallthrough_parent(ogb3));
2032 }
2033 
2034 TEST_CASE_METHOD(TApp, "OptionWithDefaults", "[app]") {
2035     int someint{2};
2036     app.add_option("-a", someint)->capture_default_str();
2037 
2038     args = {"-a1", "-a2"};
2039 
2040     CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
2041 }
2042 
2043 // Added to test ->transform
2044 TEST_CASE_METHOD(TApp, "OrderedModifyingTransforms", "[app]") {
2045     std::vector<std::string> val;
2046     auto m = app.add_option("-m", val);
__anon9f71efcd0502(std::string x) 2047     m->transform([](std::string x) { return x + "1"; });
__anon9f71efcd0602(std::string x) 2048     m->transform([](std::string x) { return x + "2"; });
2049 
2050     args = {"-mone", "-mtwo"};
2051 
2052     run();
2053 
2054     CHECK(std::vector<std::string>({"one21", "two21"}) == val);
2055 }
2056 
2057 TEST_CASE_METHOD(TApp, "ThrowingTransform", "[app]") {
2058     std::string val;
2059     auto m = app.add_option("-m,--mess", val);
__anon9f71efcd0702(std::string) 2060     m->transform([](std::string) -> std::string { throw CLI::ValidationError("My Message"); });
2061 
2062     REQUIRE_NOTHROW(run());
2063 
2064     args = {"-mone"};
2065 
2066     REQUIRE_THROWS_AS(run(), CLI::ValidationError);
2067 
2068     try {
2069         run();
2070     } catch(const CLI::ValidationError &e) {
2071         CHECK(std::string("--mess: My Message") == e.what());
2072     }
2073 }
2074 
2075 // This was added to make running a simple function on each item easier
2076 TEST_CASE_METHOD(TApp, "EachItem", "[app]") {
2077 
2078     std::vector<std::string> results;
2079     std::vector<std::string> dummy;
2080 
2081     auto opt = app.add_option("--vec", dummy);
2082 
__anon9f71efcd0802(std::string item) 2083     opt->each([&results](std::string item) { results.push_back(item); });
2084 
2085     args = {"--vec", "one", "two", "three"};
2086 
2087     run();
2088 
2089     CHECK(dummy == results);
2090 }
2091 
2092 // #128
2093 TEST_CASE_METHOD(TApp, "RepeatingMultiArgumentOptions", "[app]") {
2094     std::vector<std::string> entries;
2095     app.add_option("--entry", entries, "set a key and value")->type_name("KEY VALUE")->type_size(-2);
2096 
2097     args = {"--entry", "key1", "value1", "--entry", "key2", "value2"};
2098     REQUIRE_NOTHROW(run());
2099     CHECK(std::vector<std::string>({"key1", "value1", "key2", "value2"}) == entries);
2100 
2101     args.pop_back();
2102     REQUIRE_THROWS_AS(run(), CLI::ArgumentMismatch);
2103 }
2104 
2105 // #122
2106 TEST_CASE_METHOD(TApp, "EmptyOptionEach", "[app]") {
2107     std::string q;
__anon9f71efcd0902(std::string s) 2108     app.add_option("--each")->each([&q](std::string s) { q = s; });
2109 
2110     args = {"--each", "that"};
2111     run();
2112 
2113     CHECK("that" == q);
2114 }
2115 
2116 // #122
2117 TEST_CASE_METHOD(TApp, "EmptyOptionFail", "[app]") {
2118     std::string q;
2119     app.add_option("--each");
2120 
2121     args = {"--each", "that"};
2122     run();
2123 }
2124 
2125 TEST_CASE_METHOD(TApp, "BeforeRequirements", "[app]") {
__anon9f71efcd0a02(std::int64_t) 2126     app.add_flag_function("-a", [](std::int64_t) { throw CLI::Success(); });
__anon9f71efcd0b02(std::int64_t) 2127     app.add_flag_function("-b", [](std::int64_t) { throw CLI::CallForHelp(); });
2128 
2129     args = {"extra"};
2130     CHECK_THROWS_AS(run(), CLI::ExtrasError);
2131 
2132     args = {"-a", "extra"};
2133     CHECK_THROWS_AS(run(), CLI::Success);
2134 
2135     args = {"-b", "extra"};
2136     CHECK_THROWS_AS(run(), CLI::CallForHelp);
2137 
2138     // These run in definition order.
2139     args = {"-a", "-b", "extra"};
2140     CHECK_THROWS_AS(run(), CLI::Success);
2141 
2142     // Currently, the original order is not preserved when calling callbacks
2143     // args = {"-b", "-a", "extra"};
2144     // CHECK_THROWS_AS (run(), CLI::CallForHelp);
2145 }
2146 
2147 // #209
2148 TEST_CASE_METHOD(TApp, "CustomUserSepParse", "[app]") {
2149 
2150     std::vector<int> vals{1, 2, 3};
2151     args = {"--idx", "1,2,3"};
2152     auto opt = app.add_option("--idx", vals)->delimiter(',');
2153     run();
2154     CHECK(std::vector<int>({1, 2, 3}) == vals);
2155     std::vector<int> vals2;
2156     // check that the results vector gets the results in the same way
2157     opt->results(vals2);
2158     CHECK(vals == vals2);
2159 
2160     app.remove_option(opt);
2161 
2162     app.add_option("--idx", vals)->delimiter(',')->capture_default_str();
2163     run();
2164     CHECK(std::vector<int>({1, 2, 3}) == vals);
2165 }
2166 
2167 // #209
2168 TEST_CASE_METHOD(TApp, "DefaultUserSepParse", "[app]") {
2169 
2170     std::vector<std::string> vals;
2171     args = {"--idx", "1 2 3", "4 5 6"};
2172     auto opt = app.add_option("--idx", vals, "");
2173     run();
2174     CHECK(std::vector<std::string>({"1 2 3", "4 5 6"}) == vals);
2175     opt->delimiter(',');
2176     run();
2177     CHECK(std::vector<std::string>({"1 2 3", "4 5 6"}) == vals);
2178 }
2179 
2180 // #209
2181 TEST_CASE_METHOD(TApp, "BadUserSepParse", "[app]") {
2182 
2183     std::vector<int> vals;
2184     app.add_option("--idx", vals);
2185 
2186     args = {"--idx", "1,2,3"};
2187 
2188     CHECK_THROWS_AS(run(), CLI::ConversionError);
2189 }
2190 
2191 // #209
2192 TEST_CASE_METHOD(TApp, "CustomUserSepParse2", "[app]") {
2193 
2194     std::vector<int> vals{1, 2, 3};
2195     args = {"--idx", "1,2,"};
2196     auto opt = app.add_option("--idx", vals)->delimiter(',');
2197     run();
2198     CHECK(std::vector<int>({1, 2}) == vals);
2199 
2200     app.remove_option(opt);
2201 
2202     app.add_option("--idx", vals, "")->delimiter(',')->capture_default_str();
2203     run();
2204     CHECK(std::vector<int>({1, 2}) == vals);
2205 }
2206 
2207 TEST_CASE_METHOD(TApp, "CustomUserSepParseFunction", "[app]") {
2208 
2209     std::vector<int> vals{1, 2, 3};
2210     args = {"--idx", "1,2,3"};
__anon9f71efcd0c02(std::vector<int> v) 2211     app.add_option_function<std::vector<int>>("--idx", [&vals](std::vector<int> v) { vals = std::move(v); })
2212         ->delimiter(',');
2213     run();
2214     CHECK(std::vector<int>({1, 2, 3}) == vals);
2215 }
2216 
2217 // delimiter removal
2218 TEST_CASE_METHOD(TApp, "CustomUserSepParseToggle", "[app]") {
2219 
2220     std::vector<std::string> vals;
2221     args = {"--idx", "1,2,3"};
2222     auto opt = app.add_option("--idx", vals)->delimiter(',');
2223     run();
2224     CHECK(std::vector<std::string>({"1", "2", "3"}) == vals);
2225     opt->delimiter('\0');
2226     run();
2227     CHECK(std::vector<std::string>({"1,2,3"}) == vals);
2228     opt->delimiter(',');
2229     run();
2230     CHECK(std::vector<std::string>({"1", "2", "3"}) == vals);
2231 }
2232 
2233 // #209
2234 TEST_CASE_METHOD(TApp, "CustomUserSepParse3", "[app]") {
2235 
2236     std::vector<int> vals = {1, 2, 3};
2237     args = {"--idx",
2238             "1",
2239             ","
2240             "2"};
2241     auto opt = app.add_option("--idx", vals)->delimiter(',');
2242     run();
2243     CHECK(std::vector<int>({1, 2}) == vals);
2244     app.remove_option(opt);
2245 
2246     app.add_option("--idx", vals)->delimiter(',');
2247     run();
2248     CHECK(std::vector<int>({1, 2}) == vals);
2249 }
2250 
2251 // #209
2252 TEST_CASE_METHOD(TApp, "CustomUserSepParse4", "[app]") {
2253 
2254     std::vector<int> vals;
2255     args = {"--idx", "1,    2"};
2256     auto opt = app.add_option("--idx", vals)->delimiter(',')->capture_default_str();
2257     run();
2258     CHECK(std::vector<int>({1, 2}) == vals);
2259 
2260     app.remove_option(opt);
2261 
2262     app.add_option("--idx", vals)->delimiter(',');
2263     run();
2264     CHECK(std::vector<int>({1, 2}) == vals);
2265 }
2266 
2267 // #218
2268 TEST_CASE_METHOD(TApp, "CustomUserSepParse5", "[app]") {
2269 
2270     std::vector<std::string> bar;
2271     args = {"this", "is", "a", "test"};
2272     auto opt = app.add_option("bar", bar, "bar");
2273     run();
2274     CHECK(std::vector<std::string>({"this", "is", "a", "test"}) == bar);
2275 
2276     app.remove_option(opt);
2277     args = {"this", "is", "a", "test"};
2278     app.add_option("bar", bar, "bar")->capture_default_str();
2279     run();
2280     CHECK(std::vector<std::string>({"this", "is", "a", "test"}) == bar);
2281 }
2282 
2283 // #218
2284 TEST_CASE_METHOD(TApp, "logFormSingleDash", "[app]") {
2285     bool verbose{false};
2286     bool veryverbose{false};
2287     bool veryveryverbose{false};
2288     app.name("testargs");
2289     app.allow_extras();
2290     args = {"-v", "-vv", "-vvv"};
__anon9f71efcd0d02() 2291     app.final_callback([&]() {
2292         auto rem = app.remaining();
2293         for(auto &arg : rem) {
2294             if(arg == "-v") {
2295                 verbose = true;
2296             }
2297             if(arg == "-vv") {
2298                 veryverbose = true;
2299             }
2300             if(arg == "-vvv") {
2301                 veryveryverbose = true;
2302             }
2303         }
2304     });
2305     run();
2306     CHECK(app.remaining().size() == 3U);
2307     CHECK(verbose);
2308     CHECK(veryverbose);
2309     CHECK(veryveryverbose);
2310 }
2311