1// Copyright Leo Goodstadt 2012
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
7#include <boost/program_options/parsers.hpp>
8#include <boost/program_options/options_description.hpp>
9#include <boost/program_options/variables_map.hpp>
10#include <boost/program_options/cmdline.hpp>
11using namespace boost::program_options;
12
13#include <iostream>
14#include <sstream>
15#include <vector>
16#include <cassert>
17using namespace std;
18
19#include "minitest.hpp"
20
21
22
23//
24// like BOOST_CHECK_EQUAL but with more descriptive error message
25//
26#define CHECK_EQUAL(description, a, b) if (a != b) {std::cerr << "\n\nError:\n<<" << \
27 description << ">>\n Expected text=\"" << b << "\"\n Actual text =\"" << a << "\"\n\n"; assert(a == b);}
28
29
30// Uncomment for Debugging, removes asserts so we can see more failures!
31//#define BOOST_ERROR(description) std::cerr << description; std::cerr << "\n";
32
33
34//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
35//
36// Uncomment to print out the complete set of diagnostic messages for the different test cases
37/*
38#define CHECK_EQUAL(description, a, b) if (a != b) {std::cerr << "\n\nError: " << \
39 description << "\n Expecting\n" << b << "\n Found\n" << a << "\n\n"; } \
40 else {std::cout << description<< "\t" << b << "\n";}
41*/
42
43//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
44
45
46//
47// test exception for each specified command line style, e.g. short dash or config file
48//
49template<typename EXCEPTION>
50void test_each_exception_message(const string& test_description, const vector<const char*>& argv, options_description& desc, int style, string exception_msg, istream& is = cin)
51{
52 if (exception_msg.length() == 0)
53 return;
54 variables_map vm;
55 unsigned argc = argv.size();
56
57
58 try {
59 if (style == -1)
60 store(options: parse_config_file(is, desc), m&: vm);
61 else
62 store(options: parse_command_line(argc: argv.size(), argv: &argv[0], desc, style), m&: vm);
63 notify(m&: vm);
64 }
65 catch (EXCEPTION& e)
66 {
67 //cerr << "Correct:\n\t" << e.what() << "\n";
68 CHECK_EQUAL(test_description, e.what(), exception_msg);
69 return;
70 }
71 catch (std::exception& e)
72 {
73 // concatenate argv without boost::algorithm::join
74 string argv_txt;
75 for (unsigned ii = 0; ii < argc - 1; ++ii)
76 argv_txt += argv[ii] + string(" ");
77 if (argc)
78 argv_txt += argv[argc - 1];
79
80 BOOST_ERROR("\n<<" + test_description +
81 string(">>\n Unexpected exception type!\n Actual text =\"") + e.what() +
82 "\"\n argv =\"" + argv_txt +
83 "\"\n Expected text=\"" + exception_msg + "\"\n");
84 return;
85 }
86 BOOST_ERROR(test_description + ": No exception thrown. ");
87}
88
89
90
91
92//
93// test exception messages for all command line styles (unix/long/short/slash/config file)
94//
95// try each command line style in turn
96const int unix_style = command_line_style::unix_style;
97const int short_dash = command_line_style::allow_dash_for_short | command_line_style::allow_short | command_line_style::short_allow_adjacent | command_line_style::allow_sticky;
98const int short_slash = command_line_style::allow_slash_for_short | command_line_style::allow_short | command_line_style::short_allow_adjacent;
99const int long_dash = command_line_style::allow_long | command_line_style::long_allow_adjacent | command_line_style::allow_guessing;
100
101
102
103template<typename EXCEPTION>
104void test_exception_message(const vector<vector<const char*> >& argv,
105 options_description& desc,
106 const string& error_description,
107 const char* expected_message_template[5])
108{
109 string expected_message;
110
111 // unix
112 expected_message = expected_message_template[0];
113 test_each_exception_message<EXCEPTION>(error_description + " -- unix",
114 argv[0], desc, unix_style, expected_message);
115
116 // long dash only
117 expected_message = expected_message_template[1];
118 test_each_exception_message<EXCEPTION>(error_description + " -- long_dash",
119 argv[1], desc, long_dash, expected_message);
120
121
122 // short dash only
123 expected_message = expected_message_template[2];
124 test_each_exception_message<EXCEPTION>(error_description + " -- short_dash",
125 argv[2], desc, short_dash, expected_message);
126
127 // short slash only
128 expected_message = expected_message_template[3];
129 test_each_exception_message<EXCEPTION>(error_description + " -- short_slash",
130 argv[3], desc, short_slash, expected_message);
131
132 // config file only
133 expected_message = expected_message_template[4];
134 if (expected_message.length())
135 {
136 istringstream istrm(argv[4][0]);
137 test_each_exception_message<EXCEPTION>(error_description + " -- config_file",
138 argv[4], desc, -1, expected_message, istrm);
139 }
140
141}
142
143#define VEC_STR_PUSH_BACK(vec, c_array) \
144 vec.push_back(vector<const char*>(c_array, c_array + sizeof(c_array) / sizeof(char*)));
145
146//________________________________________________________________________________________
147//
148// invalid_option_value
149//
150//________________________________________________________________________________________
151void test_invalid_option_value_exception_msg()
152{
153 options_description desc;
154 desc.add_options()
155 ("int-option,d", value< int >(), "An option taking an integer")
156 ;
157
158 vector<vector<const char*> > argv;
159 const char* argv0[] = { "program", "-d", "A_STRING"} ; VEC_STR_PUSH_BACK(argv, argv0);
160 const char* argv1[] = { "program", "--int", "A_STRING"}; VEC_STR_PUSH_BACK(argv, argv1);
161 const char* argv2[] = { "program", "-d", "A_STRING"} ; VEC_STR_PUSH_BACK(argv, argv2);
162 const char* argv3[] = { "program", "/d", "A_STRING"} ; VEC_STR_PUSH_BACK(argv, argv3);
163 const char* argv4[] = { "int-option=A_STRING"} ; VEC_STR_PUSH_BACK(argv, argv4);
164
165 const char* expected_msg[5] = {
166 "the argument ('A_STRING') for option '--int-option' is invalid",
167 "the argument ('A_STRING') for option '--int-option' is invalid",
168 "the argument ('A_STRING') for option '-d' is invalid",
169 "the argument ('A_STRING') for option '/d' is invalid",
170 "the argument ('A_STRING') for option 'int-option' is invalid",
171 };
172
173
174 test_exception_message<invalid_option_value>(argv, desc, error_description: "invalid_option_value",
175 expected_message_template: expected_msg);
176
177
178}
179
180//________________________________________________________________________________________
181//
182// missing_value
183//
184//________________________________________________________________________________________
185void test_missing_value_exception_msg()
186{
187 options_description desc;
188 desc.add_options()
189 ("cfgfile,e", value<string>(), "the config file")
190 ("output,o", value<string>(), "the output file")
191 ;
192 vector<vector<const char*> > argv;
193 const char* argv0[] = { "program", "-e", "-e", "output.txt"} ; VEC_STR_PUSH_BACK(argv, argv0);
194 const char* argv1[] = { "program", "--cfgfile"} ; VEC_STR_PUSH_BACK(argv, argv1);
195 const char* argv2[] = { "program", "-e", "-e", "output.txt"} ; VEC_STR_PUSH_BACK(argv, argv2);
196 const char* argv3[] = { "program", "/e", "/e", "output.txt"} ; VEC_STR_PUSH_BACK(argv, argv3);
197 const char* argv4[] = { ""} ; VEC_STR_PUSH_BACK(argv, argv4);
198
199 const char* expected_msg[5] = {
200 "the required argument for option '--cfgfile' is missing",
201 "the required argument for option '--cfgfile' is missing",
202 "the required argument for option '-e' is missing",
203 "", // Ignore probable bug in cmdline::finish_option
204 //"the required argument for option '/e' is missing",
205 "",
206 };
207 test_exception_message<invalid_command_line_syntax>(argv, desc,
208 error_description: "invalid_syntax::missing_parameter",
209 expected_message_template: expected_msg);
210}
211
212//________________________________________________________________________________________
213//
214// ambiguous_option
215//
216//________________________________________________________________________________________
217void test_ambiguous_option_exception_msg()
218{
219 options_description desc;
220 desc.add_options()
221 ("cfgfile1,c", value<string>(), "the config file")
222 ("cfgfile2,o", value<string>(), "the config file")
223 ("good,g", "good option")
224 ("output,c", value<string>(), "the output file")
225 ("output", value<string>(), "the output file")
226 ;
227
228 vector<vector<const char*> > argv;
229 const char* argv0[] = {"program", "-ggc", "file", "-o", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv0);
230 const char* argv1[] = {"program", "--cfgfile", "file", "--cfgfile", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv1);
231 const char* argv2[] = {"program", "-ggc", "file", "-o", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv2);
232 const char* argv3[] = {"program", "/c", "file", "/o", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv3);
233 const char* argv4[] = { "output=output.txt\n"} ; VEC_STR_PUSH_BACK(argv, argv4);
234 const char* expected_msg[5] = {
235 "option '-c' is ambiguous and matches '--cfgfile1', and '--output'",
236 "option '--cfgfile' is ambiguous and matches '--cfgfile1', and '--cfgfile2'",
237 "option '-c' is ambiguous",
238 "option '/c' is ambiguous",
239 "option 'output' is ambiguous and matches different versions of 'output'",
240 };
241 test_exception_message<ambiguous_option>(argv, desc, error_description: "ambiguous_option",
242 expected_message_template: expected_msg);
243}
244
245//________________________________________________________________________________________
246//
247// multiple_occurrences
248//
249//________________________________________________________________________________________
250void test_multiple_occurrences_exception_msg()
251{
252 options_description desc;
253 desc.add_options()
254 ("cfgfile,c", value<string>(), "the configfile")
255 ;
256
257 vector<vector<const char*> > argv;
258 const char* argv0[] = {"program", "-c", "file", "-c", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv0);
259 const char* argv1[] = {"program", "--cfgfi", "file", "--cfgfi", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv1);
260 const char* argv2[] = {"program", "-c", "file", "-c", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv2);
261 const char* argv3[] = {"program", "/c", "file", "/c", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv3);
262 const char* argv4[] = { "cfgfile=output.txt\ncfgfile=output.txt\n"} ; VEC_STR_PUSH_BACK(argv, argv4);
263 const char* expected_msg[5] = {
264 "option '--cfgfile' cannot be specified more than once",
265 "option '--cfgfile' cannot be specified more than once",
266 "option '-c' cannot be specified more than once",
267 "option '/c' cannot be specified more than once",
268 "option 'cfgfile' cannot be specified more than once",
269 };
270 test_exception_message<multiple_occurrences>(argv, desc, error_description: "multiple_occurrences",
271 expected_message_template: expected_msg);
272}
273
274//________________________________________________________________________________________
275//
276// unknown_option
277//
278//________________________________________________________________________________________
279void test_unknown_option_exception_msg()
280{
281 options_description desc;
282 desc.add_options()
283 ("good,g", "good option")
284 ;
285
286 vector<vector<const char*> > argv;
287 const char* argv0[] = {"program", "-ggc", "file"} ; VEC_STR_PUSH_BACK(argv, argv0);
288 const char* argv1[] = {"program", "--cfgfile", "file"} ; VEC_STR_PUSH_BACK(argv, argv1);
289 const char* argv2[] = {"program", "-ggc", "file"} ; VEC_STR_PUSH_BACK(argv, argv2);
290 const char* argv3[] = {"program", "/c", "file"} ; VEC_STR_PUSH_BACK(argv, argv3);
291 const char* argv4[] = { "cfgfile=output.txt\n"} ; VEC_STR_PUSH_BACK(argv, argv4);
292 const char* expected_msg[5] = {
293 "unrecognised option '-ggc'",
294 "unrecognised option '--cfgfile'",
295 "unrecognised option '-ggc'",
296 "unrecognised option '/c'",
297 "unrecognised option 'cfgfile'",
298 };
299 test_exception_message<unknown_option>(argv, desc, error_description: "unknown_option", expected_message_template: expected_msg);
300}
301
302//________________________________________________________________________________________
303//
304// validation_error::invalid_bool_value
305//
306//________________________________________________________________________________________
307void test_invalid_bool_value_exception_msg()
308{
309 options_description desc;
310 desc.add_options()
311 ("bool_option,b", value< bool>(), "bool_option")
312 ;
313
314
315 vector<vector<const char*> > argv;
316 const char* argv0[] = {"program", "-b", "file"} ; VEC_STR_PUSH_BACK(argv, argv0);
317 const char* argv1[] = {"program", "--bool_optio", "file"} ; VEC_STR_PUSH_BACK(argv, argv1);
318 const char* argv2[] = {"program", "-b", "file"} ; VEC_STR_PUSH_BACK(argv, argv2);
319 const char* argv3[] = {"program", "/b", "file"} ; VEC_STR_PUSH_BACK(argv, argv3);
320 const char* argv4[] = { "bool_option=output.txt\n"} ; VEC_STR_PUSH_BACK(argv, argv4);
321 const char* expected_msg[5] = {
322 "the argument ('file') for option '--bool_option' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
323 "the argument ('file') for option '--bool_option' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
324 "the argument ('file') for option '-b' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
325 "the argument ('file') for option '/b' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
326 "the argument ('output.txt') for option 'bool_option' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
327 };
328 test_exception_message<validation_error>(argv,
329 desc,
330 error_description: "validation_error::invalid_bool_value",
331 expected_message_template: expected_msg);
332}
333
334
335
336
337//________________________________________________________________________________________
338//
339// validation_error::multiple_values_not_allowed
340//
341//________________________________________________________________________________________
342//
343// Strange exception: sole purpose seems to be catching multitoken() associated with a scalar
344// validation_error::multiple_values_not_allowed seems thus to be a programmer error
345//
346//
347void test_multiple_values_not_allowed_exception_msg()
348{
349 options_description desc;
350 desc.add_options()
351 ("cfgfile,c", value<string>()->multitoken(), "the config file")
352 ("good,g", "good option")
353 ("output,o", value<string>(), "the output file")
354 ;
355
356 vector<vector<const char*> > argv;
357 const char* argv0[] = { "program", "-c", "file", "c", "-o", "fritz", "hugo" } ; VEC_STR_PUSH_BACK(argv, argv0);
358 const char* argv1[] = { "program", "--cfgfil", "file", "c", "--outpu", "fritz", "hugo" } ; VEC_STR_PUSH_BACK(argv, argv1);
359 const char* argv2[] = { "program", "-c", "file", "c", "-o", "fritz", "hugo"} ; VEC_STR_PUSH_BACK(argv, argv2);
360 const char* argv3[] = { "program", "/c", "file", "c", "/o", "fritz", "hugo"} ; VEC_STR_PUSH_BACK(argv, argv3);
361 const char* argv4[] = { "" } ; VEC_STR_PUSH_BACK(argv, argv4);
362 const char* expected_msg[5] = {
363 "option '--cfgfile' only takes a single argument",
364 "option '--cfgfile' only takes a single argument",
365 "option '-c' only takes a single argument",
366 "option '/c' only takes a single argument",
367 "",
368 };
369 test_exception_message<validation_error>(argv,
370 desc,
371 error_description: "validation_error::multiple_values_not_allowed",
372 expected_message_template: expected_msg);
373}
374
375//________________________________________________________________________________________
376//
377// validation_error::at_least_one_value_required
378//
379//________________________________________________________________________________________
380//
381// Strange exception: sole purpose seems to be catching zero_tokens() associated with a scalar
382// validation_error::multiple_values_not_allowed seems thus to be a programmer error
383//
384//
385void test_at_least_one_value_required_exception_msg()
386{
387
388
389 options_description desc;
390 desc.add_options()
391 ("cfgfile,c", value<int>()->zero_tokens(), "the config file")
392 ("other,o", value<string>(), "other")
393 ;
394
395 vector<vector<const char*> > argv;
396 const char* argv0[] = { "program", "-c" } ; VEC_STR_PUSH_BACK(argv, argv0);
397 const char* argv1[] = { "program", "--cfg", "--o", "name" } ; VEC_STR_PUSH_BACK(argv, argv1);
398 const char* argv2[] = { "program", "-c" , "-o" , "name" } ; VEC_STR_PUSH_BACK(argv, argv2);
399 const char* argv3[] = { "program", "/c" } ; VEC_STR_PUSH_BACK(argv, argv3);
400 const char* argv4[] = { "" } ; VEC_STR_PUSH_BACK(argv, argv4);
401 const char* expected_msg[5] = {
402 "option '--cfgfile' requires at least one argument",
403 "option '--cfgfile' requires at least one argument",
404 "option '-c' requires at least one argument",
405 "option '/c' requires at least one argument",
406 "",
407 };
408 test_exception_message<validation_error>(argv,
409 desc,
410 error_description: "validation_error::at_least_one_value_required",
411 expected_message_template: expected_msg);
412}
413
414
415//________________________________________________________________________________________
416//
417// required_option
418//
419//________________________________________________________________________________________
420void test_required_option_exception_msg()
421{
422 options_description desc;
423 desc.add_options()
424 ("cfgfile,c", value<string>()->required(), "the config file")
425 ("good,g", "good option")
426 ("output,o", value<string>()->required(), "the output file")
427 ;
428
429 vector<vector<const char*> > argv;
430 const char* argv0[] = { "program", "-g" } ; VEC_STR_PUSH_BACK(argv, argv0);
431 const char* argv1[] = { "program", "--g" } ; VEC_STR_PUSH_BACK(argv, argv1);
432 const char* argv2[] = { "program", "-g"} ; VEC_STR_PUSH_BACK(argv, argv2);
433 const char* argv3[] = { "program", "/g"} ; VEC_STR_PUSH_BACK(argv, argv3);
434 const char* argv4[] = { "" } ; VEC_STR_PUSH_BACK(argv, argv4);
435 const char* expected_msg[5] = {
436 "the option '--cfgfile' is required but missing",
437 "the option '--cfgfile' is required but missing",
438 "the option '-c' is required but missing",
439 "the option '/c' is required but missing",
440 "the option 'cfgfile' is required but missing",
441 };
442 test_exception_message<required_option>(argv,
443 desc,
444 error_description: "required_option",
445 expected_message_template: expected_msg);
446}
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463/**
464 * Check if this is the expected exception with the right message is being thrown inside
465 * func
466*/
467template <typename EXCEPTION, typename FUNC>
468void test_exception(const string& test_name, const string& exception_txt, FUNC func)
469{
470
471 try {
472 options_description desc;
473 variables_map vm;
474 func(desc, vm);
475 }
476 catch (EXCEPTION& e)
477 {
478 CHECK_EQUAL(test_name, e.what(), exception_txt);
479 return;
480 }
481 catch (std::exception& e)
482 {
483 BOOST_ERROR(string(test_name + ":\nUnexpected exception. ") + e.what() +
484 "\nExpected text:\n" + exception_txt + "\n\n");
485 return;
486 }
487 BOOST_ERROR(test_name + ": No exception thrown. ");
488}
489
490
491
492//________________________________________________________________________________________
493//
494// check_reading_file
495//
496//________________________________________________________________________________________
497void check_reading_file(options_description& desc, variables_map& vm)
498{
499 desc.add_options()
500 ("output,o", value<string>(), "the output file");
501
502 const char* file_name = "no_such_file";
503 store(options: parse_config_file<char>(filename: file_name, desc, allow_unregistered: true), m&: vm);
504
505}
506
507
508//________________________________________________________________________________________
509//
510// config_file_wildcard
511//
512//________________________________________________________________________________________
513void config_file_wildcard(options_description& desc, variables_map& vm)
514{
515 desc.add_options()
516 ("outpu*", value<string>(), "the output file1")
517 ("outp*", value<string>(), "the output file2")
518 ;
519 istringstream is("output1=whichone\noutput2=whichone\n");
520 store(options: parse_config_file(is, desc), m&: vm);
521}
522
523//________________________________________________________________________________________
524//
525// invalid_syntax::unrecognized_line
526//
527//________________________________________________________________________________________
528void unrecognized_line(options_description& desc, variables_map& vm)
529{
530 istringstream is("funny wierd line\n");
531 store(options: parse_config_file(is, desc), m&: vm);
532}
533
534//________________________________________________________________________________________
535//
536// abbreviated_options_in_config_file
537//
538//________________________________________________________________________________________
539void abbreviated_options_in_config_file(options_description& desc, variables_map& vm)
540{
541 desc.add_options()(",o", value<string>(), "the output file");
542 istringstream is("o=output.txt\n");
543 store(options: parse_config_file(is, desc), m&: vm);
544}
545
546
547//________________________________________________________________________________________
548//
549// too_many_positional_options
550//
551//________________________________________________________________________________________
552void too_many_positional_options(options_description& desc, variables_map& vm)
553{
554 const char* argv[] = {"program", "1", "2", "3"};
555 positional_options_description positional_args;
556 positional_args.add(name: "two_positional_arguments", max_count: 2);
557 store(options: command_line_parser(4, argv).options(desc).positional(desc: positional_args).run(), m&: vm);
558}
559
560
561//________________________________________________________________________________________
562//
563// invalid_command_line_style
564//
565//________________________________________________________________________________________
566
567void test_invalid_command_line_style_exception_msg()
568{
569 string test_name = "invalid_command_line_style";
570 using namespace command_line_style;
571 options_description desc;
572 desc.add_options()("output,o", value<string>(), "the output file");
573
574 vector<int> invalid_styles;
575 invalid_styles.push_back(x: allow_short | short_allow_adjacent);
576 invalid_styles.push_back(x: allow_short | allow_dash_for_short);
577 invalid_styles.push_back(x: allow_long);
578 vector<string> invalid_diagnostics;
579 invalid_diagnostics.push_back(x: "boost::program_options misconfiguration: choose one "
580 "or other of 'command_line_style::allow_slash_for_short' "
581 "(slashes) or 'command_line_style::allow_dash_for_short' "
582 "(dashes) for short options.");
583 invalid_diagnostics.push_back(x: "boost::program_options misconfiguration: choose one "
584 "or other of 'command_line_style::short_allow_next' "
585 "(whitespace separated arguments) or "
586 "'command_line_style::short_allow_adjacent' ('=' "
587 "separated arguments) for short options.");
588 invalid_diagnostics.push_back(x: "boost::program_options misconfiguration: choose one "
589 "or other of 'command_line_style::long_allow_next' "
590 "(whitespace separated arguments) or "
591 "'command_line_style::long_allow_adjacent' ('=' "
592 "separated arguments) for long options.");
593
594
595 const char* argv[] = {"program"};
596 variables_map vm;
597 for (unsigned ii = 0; ii < 3; ++ii)
598 {
599 bool exception_thrown = false;
600 try
601 {
602 store(options: parse_command_line(argc: 1, argv, desc, style: invalid_styles[ii]), m&: vm);
603 }
604 catch (invalid_command_line_style& e)
605 {
606 string error_msg("arguments are not allowed for unabbreviated option names");
607 CHECK_EQUAL(test_name, e.what(), invalid_diagnostics[ii]);
608 exception_thrown = true;
609 }
610 catch (std::exception& e)
611 {
612 BOOST_ERROR(string(test_name + ":\nUnexpected exception. ") + e.what() +
613 "\nExpected text:\n" + invalid_diagnostics[ii] + "\n");
614 exception_thrown = true;
615 }
616 if (!exception_thrown)
617 {
618 BOOST_ERROR(test_name << ": No exception thrown. ");
619 }
620 }
621}
622
623void test_empty_value_inner(options_description &opts, variables_map& vm) {
624 positional_options_description popts;
625 opts.add_options()("foo", value<uint32_t>()->value_name(name: "<time>")->required());
626 popts.add(name: "foo", max_count: 1);
627 vector<string> tokens(1, "");
628 parsed_options parsed = command_line_parser(tokens)
629 .style(xstyle: command_line_style::default_style & ~command_line_style::allow_guessing)
630 .options(desc: opts)
631 .positional(desc: popts)
632 .run();
633 store(options: parsed, m&: vm);
634}
635
636void test_empty_value() {
637 // Test that passing empty token for an option that requires integer does not result
638 // in out-of-range error in error reporting code.
639 test_exception<invalid_option_value>(
640 test_name: "test_empty_value",
641 exception_txt: "the argument for option '--foo' is invalid",
642 func: test_empty_value_inner);
643}
644
645int main(int /*ac*/, char** /*av*/)
646{
647 test_ambiguous_option_exception_msg();
648 test_unknown_option_exception_msg();
649 test_multiple_occurrences_exception_msg();
650 test_missing_value_exception_msg();
651 test_invalid_option_value_exception_msg();
652 test_invalid_bool_value_exception_msg();
653 test_multiple_values_not_allowed_exception_msg();
654 test_required_option_exception_msg();
655 test_at_least_one_value_required_exception_msg();
656 test_empty_value();
657
658 string test_name;
659 string expected_message;
660
661
662 // check_reading_file
663 test_name = "check_reading_file";
664 expected_message = "can not read options configuration file 'no_such_file'";
665 test_exception<reading_file>(test_name, exception_txt: expected_message, func: check_reading_file);
666
667 // config_file_wildcard
668 test_name = "config_file_wildcard";
669 expected_message = "options 'outpu*' and 'outp*' will both match the same arguments from the configuration file";
670 test_exception<error>(test_name, exception_txt: expected_message, func: config_file_wildcard);
671
672 // unrecognized_line
673 test_name = "unrecognized_line";
674 expected_message = "the options configuration file contains an invalid line 'funny wierd line'";
675 test_exception<invalid_syntax>(test_name, exception_txt: expected_message, func: unrecognized_line);
676
677
678 // abbreviated_options_in_config_file
679 test_name = "abbreviated_options_in_config_file";
680 expected_message = "abbreviated option names are not permitted in options configuration files";
681 test_exception<error>(test_name, exception_txt: expected_message, func: abbreviated_options_in_config_file);
682
683 test_name = "too_many_positional_options";
684 expected_message = "too many positional options have been specified on the command line";
685 test_exception<too_many_positional_options_error>(
686 test_name, exception_txt: expected_message, func: too_many_positional_options);
687
688 test_invalid_command_line_style_exception_msg();
689
690
691 return 0;
692}
693
694

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