1// Copyright Vladimir Prus 2002-2004.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt
4// or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#include <boost/program_options/cmdline.hpp>
7#include <boost/program_options/options_description.hpp>
8#include <boost/program_options/detail/cmdline.hpp>
9using namespace boost::program_options;
10using boost::program_options::detail::cmdline;
11
12#include <iostream>
13#include <sstream>
14#include <vector>
15#include <cassert>
16using namespace std;
17
18#include "minitest.hpp"
19
20/* To facilitate testing, declare a number of error codes. Otherwise,
21 we'd have to specify the type of exception that should be thrown.
22*/
23
24const int s_success = 0;
25const int s_unknown_option = 1;
26const int s_ambiguous_option = 2;
27const int s_long_not_allowed = 3;
28const int s_long_adjacent_not_allowed = 4;
29const int s_short_adjacent_not_allowed = 5;
30const int s_empty_adjacent_parameter = 6;
31const int s_missing_parameter = 7;
32const int s_extra_parameter = 8;
33const int s_unrecognized_line = 9;
34
35int translate_syntax_error_kind(invalid_command_line_syntax::kind_t k)
36{
37 invalid_command_line_syntax::kind_t table[] = {
38 invalid_command_line_syntax::long_not_allowed,
39 invalid_command_line_syntax::long_adjacent_not_allowed,
40 invalid_command_line_syntax::short_adjacent_not_allowed,
41 invalid_command_line_syntax::empty_adjacent_parameter,
42 invalid_command_line_syntax::missing_parameter,
43 invalid_command_line_syntax::extra_parameter,
44 invalid_command_line_syntax::unrecognized_line
45 };
46 invalid_command_line_syntax::kind_t *b, *e, *i;
47 b = table;
48 e = table + sizeof(table)/sizeof(table[0]);
49 i = std::find(first: b, last: e, val: k);
50 assert(i != e);
51 return std::distance(first: b, last: i) + 3;
52}
53
54struct test_case {
55 const char* input;
56 int expected_status;
57 const char* expected_result;
58};
59
60
61/* Parses the syntax description in 'syntax' and initialized
62 'cmd' accordingly'
63 The "boost::program_options" in parameter type is needed because CW9
64 has std::detail and it causes an ambiguity.
65*/
66void apply_syntax(options_description& desc,
67 const char* syntax)
68{
69
70 string s;
71 stringstream ss;
72 ss << syntax;
73 while(ss >> s) {
74 value_semantic* v = 0;
75
76 if (*(s.end()-1) == '=') {
77 v = value<string>();
78 s.resize(n: s.size()-1);
79 } else if (*(s.end()-1) == '?') {
80 v = value<string>()->implicit_value(v: "default");
81 s.resize(n: s.size()-1);
82 } else if (*(s.end()-1) == '*') {
83 v = value<vector<string> >()->multitoken();
84 s.resize(n: s.size()-1);
85 } else if (*(s.end()-1) == '+') {
86 v = value<vector<string> >()->multitoken();
87 s.resize(n: s.size()-1);
88 }
89 if (v) {
90 desc.add_options()
91 (s.c_str(), v, "");
92 } else {
93 desc.add_options()
94 (s.c_str(), "");
95 }
96 }
97}
98
99void test_cmdline(const char* syntax,
100 command_line_style::style_t style,
101 const test_case* cases)
102{
103 for (int i = 0; cases[i].input; ++i) {
104 // Parse input
105 vector<string> xinput;
106 {
107 string s;
108 stringstream ss;
109 ss << cases[i].input;
110 while (ss >> s) {
111 xinput.push_back(x: s);
112 }
113 }
114 options_description desc;
115 apply_syntax(desc, syntax);
116
117 cmdline cmd(xinput);
118 cmd.style(style);
119 cmd.set_options_description(desc);
120
121
122 string result;
123 int status = 0;
124
125 try {
126 vector<option> options = cmd.run();
127
128 for(unsigned j = 0; j < options.size(); ++j)
129 {
130 option opt = options[j];
131
132 if (opt.position_key != -1) {
133 if (!result.empty())
134 result += " ";
135 result += opt.value[0];
136 } else {
137 if (!result.empty())
138 result += " ";
139 result += opt.string_key + ":";
140 for (size_t k = 0; k < opt.value.size(); ++k) {
141 if (k != 0)
142 result += "-";
143 result += opt.value[k];
144 }
145 }
146 }
147 }
148 catch(unknown_option&) {
149 status = s_unknown_option;
150 }
151 catch(ambiguous_option&) {
152 status = s_ambiguous_option;
153 }
154 catch(invalid_command_line_syntax& e) {
155 status = translate_syntax_error_kind(k: e.kind());
156 }
157 BOOST_CHECK_EQUAL(status, cases[i].expected_status);
158 BOOST_CHECK_EQUAL(result, cases[i].expected_result);
159 }
160}
161
162void test_long_options()
163{
164 using namespace command_line_style;
165 cmdline::style_t style = cmdline::style_t(
166 allow_long | long_allow_adjacent);
167
168 test_case test_cases1[] = {
169 // Test that long options are recognized and everything else
170 // is treated like arguments
171 {.input: "--foo foo -123 /asd", .expected_status: s_success, .expected_result: "foo: foo -123 /asd"},
172
173 // Unknown option
174 {.input: "--unk", .expected_status: s_unknown_option, .expected_result: ""},
175
176 // Test that abbreviated names do not work
177 {.input: "--fo", .expected_status: s_unknown_option, .expected_result: ""},
178
179 // Test for disallowed parameter
180 {.input: "--foo=13", .expected_status: s_extra_parameter, .expected_result: ""},
181
182 // Test option with required parameter
183 {.input: "--bar=", .expected_status: s_empty_adjacent_parameter, .expected_result: ""},
184 {.input: "--bar", .expected_status: s_missing_parameter, .expected_result: ""},
185
186 {.input: "--bar=123", .expected_status: s_success, .expected_result: "bar:123"},
187 {.input: 0, .expected_status: 0, .expected_result: 0}
188 };
189 test_cmdline(syntax: "foo bar=", style, cases: test_cases1);
190
191
192 style = cmdline::style_t(
193 allow_long | long_allow_next);
194
195 test_case test_cases2[] = {
196 {.input: "--bar 10", .expected_status: s_success, .expected_result: "bar:10"},
197 {.input: "--bar", .expected_status: s_missing_parameter, .expected_result: ""},
198 // Since --bar accepts a parameter, --foo is
199 // considered a value, even though it looks like
200 // an option.
201 {.input: "--bar --foo", .expected_status: s_success, .expected_result: "bar:--foo"},
202 {.input: 0, .expected_status: 0, .expected_result: 0}
203 };
204 test_cmdline(syntax: "foo bar=", style, cases: test_cases2);
205 style = cmdline::style_t(
206 allow_long | long_allow_adjacent
207 | long_allow_next);
208
209 test_case test_cases3[] = {
210 {.input: "--bar=10", .expected_status: s_success, .expected_result: "bar:10"},
211 {.input: "--bar 11", .expected_status: s_success, .expected_result: "bar:11"},
212 {.input: 0, .expected_status: 0, .expected_result: 0}
213 };
214 test_cmdline(syntax: "foo bar=", style, cases: test_cases3);
215
216 style = cmdline::style_t(
217 allow_long | long_allow_adjacent
218 | long_allow_next | case_insensitive);
219
220 // Test case insensitive style.
221 // Note that option names are normalized to lower case.
222 test_case test_cases4[] = {
223 {.input: "--foo", .expected_status: s_success, .expected_result: "foo:"},
224 {.input: "--Foo", .expected_status: s_success, .expected_result: "foo:"},
225 {.input: "--bar=Ab", .expected_status: s_success, .expected_result: "bar:Ab"},
226 {.input: "--Bar=ab", .expected_status: s_success, .expected_result: "bar:ab"},
227 {.input: "--giz", .expected_status: s_success, .expected_result: "Giz:"},
228 {.input: 0, .expected_status: 0, .expected_result: 0}
229 };
230 test_cmdline(syntax: "foo bar= baz? Giz", style, cases: test_cases4);
231}
232
233void test_short_options()
234{
235 using namespace command_line_style;
236 cmdline::style_t style;
237
238 style = cmdline::style_t(
239 allow_short | allow_dash_for_short
240 | short_allow_adjacent);
241
242 test_case test_cases1[] = {
243 {.input: "-d d /bar", .expected_status: s_success, .expected_result: "-d: d /bar"},
244 // This is treated as error when long options are disabled
245 {.input: "--foo", .expected_status: s_success, .expected_result: "--foo"},
246 {.input: "-d13", .expected_status: s_extra_parameter, .expected_result: ""},
247 {.input: "-f14", .expected_status: s_success, .expected_result: "-f:14"},
248 {.input: "-g -f1", .expected_status: s_success, .expected_result: "-g: -f:1"},
249 {.input: "-f", .expected_status: s_missing_parameter, .expected_result: ""},
250 {.input: 0, .expected_status: 0, .expected_result: 0}
251 };
252 test_cmdline(syntax: ",d ,f= ,g", style, cases: test_cases1);
253
254 style = cmdline::style_t(
255 allow_short | allow_dash_for_short
256 | short_allow_next);
257
258 test_case test_cases2[] = {
259 {.input: "-f 13", .expected_status: s_success, .expected_result: "-f:13"},
260 {.input: "-f -13", .expected_status: s_success, .expected_result: "-f:-13"},
261 {.input: "-f", .expected_status: s_missing_parameter, .expected_result: ""},
262 {.input: "-f /foo", .expected_status: s_success, .expected_result: "-f:/foo"},
263 {.input: "-f -d", .expected_status: s_missing_parameter, .expected_result: ""},
264 {.input: 0, .expected_status: 0, .expected_result: 0}
265 };
266 test_cmdline(syntax: ",d ,f=", style, cases: test_cases2);
267
268 style = cmdline::style_t(
269 allow_short | short_allow_next
270 | allow_dash_for_short | short_allow_adjacent);
271
272 test_case test_cases3[] = {
273 {.input: "-f10", .expected_status: s_success, .expected_result: "-f:10"},
274 {.input: "-f 10", .expected_status: s_success, .expected_result: "-f:10"},
275 {.input: "-f -d", .expected_status: s_missing_parameter, .expected_result: ""},
276 {.input: 0, .expected_status: 0, .expected_result: 0}
277 };
278 test_cmdline(syntax: ",d ,f=", style, cases: test_cases3);
279
280 style = cmdline::style_t(
281 allow_short | short_allow_next
282 | allow_dash_for_short
283 | short_allow_adjacent | allow_sticky);
284
285 test_case test_cases4[] = {
286 {.input: "-de", .expected_status: s_success, .expected_result: "-d: -e:"},
287 {.input: "-df10", .expected_status: s_success, .expected_result: "-d: -f:10"},
288 // FIXME: review
289 //{"-d12", s_extra_parameter, ""},
290 {.input: "-f12", .expected_status: s_success, .expected_result: "-f:12"},
291 {.input: "-fe", .expected_status: s_success, .expected_result: "-f:e"},
292 {.input: 0, .expected_status: 0, .expected_result: 0}
293 };
294 test_cmdline(syntax: ",d ,f= ,e", style, cases: test_cases4);
295
296}
297
298
299void test_dos_options()
300{
301 using namespace command_line_style;
302 cmdline::style_t style;
303
304 style = cmdline::style_t(
305 allow_short
306 | allow_slash_for_short | short_allow_adjacent);
307
308 test_case test_cases1[] = {
309 {.input: "/d d -bar", .expected_status: s_success, .expected_result: "-d: d -bar"},
310 {.input: "--foo", .expected_status: s_success, .expected_result: "--foo"},
311 {.input: "/d13", .expected_status: s_extra_parameter, .expected_result: ""},
312 {.input: "/f14", .expected_status: s_success, .expected_result: "-f:14"},
313 {.input: "/f", .expected_status: s_missing_parameter, .expected_result: ""},
314 {.input: 0, .expected_status: 0, .expected_result: 0}
315 };
316 test_cmdline(syntax: ",d ,f=", style, cases: test_cases1);
317
318 style = cmdline::style_t(
319 allow_short
320 | allow_slash_for_short | short_allow_next
321 | short_allow_adjacent | allow_sticky);
322
323 test_case test_cases2[] = {
324 {.input: "/de", .expected_status: s_extra_parameter, .expected_result: ""},
325 {.input: "/fe", .expected_status: s_success, .expected_result: "-f:e"},
326 {.input: 0, .expected_status: 0, .expected_result: 0}
327 };
328 test_cmdline(syntax: ",d ,f= ,e", style, cases: test_cases2);
329
330}
331
332
333void test_disguised_long()
334{
335 using namespace command_line_style;
336 cmdline::style_t style;
337
338 style = cmdline::style_t(
339 allow_short | short_allow_adjacent
340 | allow_dash_for_short
341 | short_allow_next | allow_long_disguise
342 | long_allow_adjacent);
343
344 test_case test_cases1[] = {
345 {.input: "-foo -f", .expected_status: s_success, .expected_result: "foo: foo:"},
346 {.input: "-goo=x -gy", .expected_status: s_success, .expected_result: "goo:x goo:y"},
347 {.input: "-bee=x -by", .expected_status: s_success, .expected_result: "bee:x bee:y"},
348 {.input: 0, .expected_status: 0, .expected_result: 0}
349 };
350 test_cmdline(syntax: "foo,f goo,g= bee,b?", style, cases: test_cases1);
351
352 style = cmdline::style_t(style | allow_slash_for_short);
353 test_case test_cases2[] = {
354 {.input: "/foo -f", .expected_status: s_success, .expected_result: "foo: foo:"},
355 {.input: "/goo=x", .expected_status: s_success, .expected_result: "goo:x"},
356 {.input: 0, .expected_status: 0, .expected_result: 0}
357 };
358 test_cmdline(syntax: "foo,f goo,g= bee,b?", style, cases: test_cases2);
359}
360
361void test_guessing()
362{
363 using namespace command_line_style;
364 cmdline::style_t style;
365
366 style = cmdline::style_t(
367 allow_short | short_allow_adjacent
368 | allow_dash_for_short
369 | allow_long | long_allow_adjacent
370 | allow_guessing | allow_long_disguise);
371
372 test_case test_cases1[] = {
373 {.input: "--opt1", .expected_status: s_success, .expected_result: "opt123:"},
374 {.input: "--opt", .expected_status: s_ambiguous_option, .expected_result: ""},
375 {.input: "--f=1", .expected_status: s_success, .expected_result: "foo:1"},
376 {.input: "-far", .expected_status: s_success, .expected_result: "foo:ar"},
377 {.input: 0, .expected_status: 0, .expected_result: 0}
378 };
379 test_cmdline(syntax: "opt123 opt56 foo,f=", style, cases: test_cases1);
380
381 test_case test_cases2[] = {
382 {.input: "--fname file --fname2 file2", .expected_status: s_success, .expected_result: "fname: file fname2: file2"},
383 {.input: "--fnam file --fnam file2", .expected_status: s_ambiguous_option, .expected_result: ""},
384 {.input: "--fnam file --fname2 file2", .expected_status: s_ambiguous_option, .expected_result: ""},
385 {.input: "--fname2 file2 --fnam file", .expected_status: s_ambiguous_option, .expected_result: ""},
386 {.input: 0, .expected_status: 0, .expected_result: 0}
387 };
388 test_cmdline(syntax: "fname fname2", style, cases: test_cases2);
389}
390
391void test_arguments()
392{
393 using namespace command_line_style;
394 cmdline::style_t style;
395
396 style = cmdline::style_t(
397 allow_short | allow_long
398 | allow_dash_for_short
399 | short_allow_adjacent | long_allow_adjacent);
400
401 test_case test_cases1[] = {
402 {.input: "-f file -gx file2", .expected_status: s_success, .expected_result: "-f: file -g:x file2"},
403 {.input: "-f - -gx - -- -e", .expected_status: s_success, .expected_result: "-f: - -g:x - -e"},
404 {.input: 0, .expected_status: 0, .expected_result: 0}
405 };
406 test_cmdline(syntax: ",f ,g= ,e", style, cases: test_cases1);
407
408 // "--" should stop options regardless of whether long options are
409 // allowed or not.
410
411 style = cmdline::style_t(
412 allow_short | short_allow_adjacent
413 | allow_dash_for_short);
414
415 test_case test_cases2[] = {
416 {.input: "-f - -gx - -- -e", .expected_status: s_success, .expected_result: "-f: - -g:x - -e"},
417 {.input: 0, .expected_status: 0, .expected_result: 0}
418 };
419 test_cmdline(syntax: ",f ,g= ,e", style, cases: test_cases2);
420}
421
422void test_prefix()
423{
424 using namespace command_line_style;
425 cmdline::style_t style;
426
427 style = cmdline::style_t(
428 allow_short | allow_long
429 | allow_dash_for_short
430 | short_allow_adjacent | long_allow_adjacent
431 );
432
433 test_case test_cases1[] = {
434 {.input: "--foo.bar=12", .expected_status: s_success, .expected_result: "foo.bar:12"},
435 {.input: 0, .expected_status: 0, .expected_result: 0}
436 };
437
438 test_cmdline(syntax: "foo*=", style, cases: test_cases1);
439}
440
441
442pair<string, string> at_option_parser(string const&s)
443{
444 if ('@' == s[0])
445 return std::make_pair(x: string("response-file"), y: s.substr(pos: 1));
446 else
447 return pair<string, string>();
448}
449
450pair<string, string> at_option_parser_broken(string const&s)
451{
452 if ('@' == s[0])
453 return std::make_pair(x: string("some garbage"), y: s.substr(pos: 1));
454 else
455 return pair<string, string>();
456}
457
458
459
460void test_additional_parser()
461{
462 options_description desc;
463 desc.add_options()
464 ("response-file", value<string>(), "response file")
465 ("foo", value<int>(), "foo")
466 ("bar,baz", value<int>(), "bar")
467 ;
468
469 vector<string> input;
470 input.push_back(x: "@config");
471 input.push_back(x: "--foo=1");
472 input.push_back(x: "--baz=11");
473
474 cmdline cmd(input);
475 cmd.set_options_description(desc);
476 cmd.set_additional_parser(at_option_parser);
477
478 vector<option> result = cmd.run();
479
480 BOOST_REQUIRE(result.size() == 3);
481 BOOST_CHECK_EQUAL(result[0].string_key, "response-file");
482 BOOST_CHECK_EQUAL(result[0].value[0], "config");
483 BOOST_CHECK_EQUAL(result[1].string_key, "foo");
484 BOOST_CHECK_EQUAL(result[1].value[0], "1");
485 BOOST_CHECK_EQUAL(result[2].string_key, "bar");
486 BOOST_CHECK_EQUAL(result[2].value[0], "11");
487
488 // Test that invalid options returned by additional style
489 // parser are detected.
490 cmdline cmd2(input);
491 cmd2.set_options_description(desc);
492 cmd2.set_additional_parser(at_option_parser_broken);
493
494 BOOST_CHECK_THROW(cmd2.run(), unknown_option);
495
496}
497
498vector<option> at_option_parser2(vector<string>& args)
499{
500 vector<option> result;
501 if ('@' == args[0][0]) {
502 // Simulate reading the response file.
503 result.push_back(x: option("foo", vector<string>(1, "1")));
504 result.push_back(x: option("bar", vector<string>(1, "1")));
505 args.erase(position: args.begin());
506 }
507 return result;
508}
509
510
511void test_style_parser()
512{
513 options_description desc;
514 desc.add_options()
515 ("foo", value<int>(), "foo")
516 ("bar", value<int>(), "bar")
517 ;
518
519 vector<string> input;
520 input.push_back(x: "@config");
521
522 cmdline cmd(input);
523 cmd.set_options_description(desc);
524 cmd.extra_style_parser(s: at_option_parser2);
525
526 vector<option> result = cmd.run();
527
528 BOOST_REQUIRE(result.size() == 2);
529 BOOST_CHECK_EQUAL(result[0].string_key, "foo");
530 BOOST_CHECK_EQUAL(result[0].value[0], "1");
531 BOOST_CHECK_EQUAL(result[1].string_key, "bar");
532 BOOST_CHECK_EQUAL(result[1].value[0], "1");
533}
534
535void test_unregistered()
536{
537 // Check unregisted option when no options are registed at all.
538 options_description desc;
539
540 vector<string> input;
541 input.push_back(x: "--foo=1");
542 input.push_back(x: "--bar");
543 input.push_back(x: "1");
544 input.push_back(x: "-b");
545 input.push_back(x: "-biz");
546
547 cmdline cmd(input);
548 cmd.set_options_description(desc);
549 cmd.allow_unregistered();
550
551 vector<option> result = cmd.run();
552 BOOST_REQUIRE(result.size() == 5);
553 // --foo=1
554 BOOST_CHECK_EQUAL(result[0].string_key, "foo");
555 BOOST_CHECK_EQUAL(result[0].unregistered, true);
556 BOOST_CHECK_EQUAL(result[0].value[0], "1");
557 // --bar
558 BOOST_CHECK_EQUAL(result[1].string_key, "bar");
559 BOOST_CHECK_EQUAL(result[1].unregistered, true);
560 BOOST_CHECK(result[1].value.empty());
561 // '1' is considered a positional option, not a value to
562 // --bar
563 BOOST_CHECK(result[2].string_key.empty());
564 BOOST_CHECK(result[2].position_key == 0);
565 BOOST_CHECK_EQUAL(result[2].unregistered, false);
566 BOOST_CHECK_EQUAL(result[2].value[0], "1");
567 // -b
568 BOOST_CHECK_EQUAL(result[3].string_key, "-b");
569 BOOST_CHECK_EQUAL(result[3].unregistered, true);
570 BOOST_CHECK(result[3].value.empty());
571 // -biz
572 BOOST_CHECK_EQUAL(result[4].string_key, "-b");
573 BOOST_CHECK_EQUAL(result[4].unregistered, true);
574 BOOST_CHECK_EQUAL(result[4].value[0], "iz");
575
576 // Check sticky short options together with unregisted options.
577
578 desc.add_options()
579 ("help,h", "")
580 ("magic,m", value<string>(), "")
581 ;
582
583 input.clear();
584 input.push_back(x: "-hc");
585 input.push_back(x: "-mc");
586
587
588 cmdline cmd2(input);
589 cmd2.set_options_description(desc);
590 cmd2.allow_unregistered();
591
592 result = cmd2.run();
593
594 BOOST_REQUIRE(result.size() == 3);
595 BOOST_CHECK_EQUAL(result[0].string_key, "help");
596 BOOST_CHECK_EQUAL(result[0].unregistered, false);
597 BOOST_CHECK(result[0].value.empty());
598 BOOST_CHECK_EQUAL(result[1].string_key, "-c");
599 BOOST_CHECK_EQUAL(result[1].unregistered, true);
600 BOOST_CHECK(result[1].value.empty());
601 BOOST_CHECK_EQUAL(result[2].string_key, "magic");
602 BOOST_CHECK_EQUAL(result[2].unregistered, false);
603 BOOST_CHECK_EQUAL(result[2].value[0], "c");
604
605 // CONSIDER:
606 // There's a corner case:
607 // -foo
608 // when 'allow_long_disguise' is set. Should this be considered
609 // disguised long option 'foo' or short option '-f' with value 'oo'?
610 // It's not clear yet, so I'm leaving the decision till later.
611}
612
613void test_implicit_value()
614{
615 using namespace command_line_style;
616 cmdline::style_t style;
617
618 style = cmdline::style_t(
619 allow_long | long_allow_adjacent
620 );
621
622 test_case test_cases1[] = {
623 // 'bar' does not even look like option, so is consumed
624 {.input: "--foo bar", .expected_status: s_success, .expected_result: "foo:bar"},
625 // '--bar' looks like option, and such option exists, so we don't consume this token
626 {.input: "--foo --bar", .expected_status: s_success, .expected_result: "foo: bar:"},
627 // '--biz' looks like option, but does not match any existing one.
628 // Presently this results in parse error, since
629 // (1) in cmdline.cpp:finish_option, we only consume following tokens if they are
630 // requires
631 // (2) in cmdline.cpp:run, we let options consume following positional options
632 // For --biz, an exception is thrown between 1 and 2.
633 // We might want to fix that in future.
634 {.input: "--foo --biz", .expected_status: s_unknown_option, .expected_result: ""},
635 {.input: 0, .expected_status: 0, .expected_result: 0}
636 };
637
638 test_cmdline(syntax: "foo? bar?", style, cases: test_cases1);
639}
640
641int main(int /*ac*/, char** /*av*/)
642{
643 test_long_options();
644 test_short_options();
645 test_dos_options();
646 test_disguised_long();
647 test_guessing();
648 test_arguments();
649 test_prefix();
650 test_additional_parser();
651 test_style_parser();
652 test_unregistered();
653 test_implicit_value();
654
655 return 0;
656}
657

source code of boost/libs/program_options/test/cmdline_test.cpp