1 // Copyright Sascha Ochsenknecht 2009.
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>
11 using namespace boost::program_options;
12 
13 #include <iostream>
14 #include <sstream>
15 #include <vector>
16 #include <cassert>
17 using namespace std;
18 
19 #include "minitest.hpp"
20 
21 
test_ambiguous()22 void test_ambiguous()
23 {
24     options_description desc;
25     desc.add_options()
26         ("cfgfile,c", value<string>()->multitoken(), "the config file")
27         ("output,c", value<string>(), "the output file")
28         ("output,o", value<string>(), "the output file")
29     ;
30 
31     const char* cmdline[] = {"program", "-c", "file", "-o", "anotherfile"};
32 
33     variables_map vm;
34     try {
35        store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
36                                     const_cast<char**>(cmdline), desc), vm);
37     }
38     catch (ambiguous_option& e)
39     {
40         BOOST_CHECK_EQUAL(e.alternatives().size(), 2);
41         BOOST_CHECK_EQUAL(e.get_option_name(), "-c");
42         BOOST_CHECK_EQUAL(e.alternatives()[0], "cfgfile");
43         BOOST_CHECK_EQUAL(e.alternatives()[1], "output");
44     }
45 }
46 
47 
48 
test_unknown_option()49 void test_unknown_option()
50 {
51    options_description desc;
52    desc.add_options()
53         ("cfgfile,c", value<string>(), "the configfile")
54       ;
55 
56    const char* cmdline[] = {"program", "-c", "file", "-f", "anotherfile"};
57 
58    variables_map vm;
59    try {
60       store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
61                                     const_cast<char**>(cmdline), desc), vm);
62    }
63    catch (unknown_option& e)
64    {
65       BOOST_CHECK_EQUAL(e.get_option_name(), "-f");
66       BOOST_CHECK_EQUAL(string(e.what()), "unrecognised option '-f'");
67    }
68 }
69 
70 
71 
test_multiple_values()72 void test_multiple_values()
73 {
74    options_description desc;
75    desc.add_options()
76         ("cfgfile,c", value<string>()->multitoken(), "the config file")
77         ("output,o", value<string>(), "the output file")
78       ;
79 
80    const char* cmdline[] = { "program", "-o", "fritz", "hugo", "--cfgfile", "file", "c", "-o", "text.out" };
81 
82    variables_map vm;
83    try {
84       store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
85                                     const_cast<char**>(cmdline), desc), vm);
86       notify(vm);
87    }
88    catch (validation_error& e)
89    {
90       // TODO: this is currently validation_error, shouldn't it be multiple_values ???
91       //
92       //   multiple_values is thrown only at one place untyped_value::xparse(),
93       //    but I think this can never be reached
94       //   because: untyped_value always has one value and this is filtered before reach specific
95       //   validation and parsing
96       //
97       BOOST_CHECK_EQUAL(e.get_option_name(), "--cfgfile");
98       BOOST_CHECK_EQUAL(string(e.what()), "option '--cfgfile' only takes a single argument");
99    }
100 }
101 
102 
103 
test_multiple_occurrences()104 void test_multiple_occurrences()
105 {
106    options_description desc;
107    desc.add_options()
108         ("cfgfile,c", value<string>(), "the configfile")
109       ;
110 
111    const char* cmdline[] = {"program", "--cfgfile", "file", "-c", "anotherfile"};
112 
113    variables_map vm;
114    try {
115       store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
116                                     const_cast<char**>(cmdline), desc), vm);
117       notify(vm);
118    }
119    catch (multiple_occurrences& e)
120    {
121       BOOST_CHECK_EQUAL(e.get_option_name(), "--cfgfile");
122       BOOST_CHECK_EQUAL(string(e.what()), "option '--cfgfile' cannot be specified more than once");
123    }
124 }
125 
126 
127 
test_missing_value()128 void test_missing_value()
129 {
130     options_description desc;
131     desc.add_options()
132         ("cfgfile,c", value<string>()->multitoken(), "the config file")
133         ("output,o", value<string>(), "the output file")
134     ;
135     // missing value for option '-c'
136     const char* cmdline[] = { "program", "-c", "-c", "output.txt"};
137 
138     variables_map vm;
139 
140     try {
141       store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
142                                        const_cast<char**>(cmdline), desc), vm);
143       notify(vm);
144    }
145    catch (invalid_command_line_syntax& e)
146    {
147       BOOST_CHECK_EQUAL(e.kind(), invalid_syntax::missing_parameter);
148       BOOST_CHECK_EQUAL(e.tokens(), "--cfgfile");
149    }
150 }
151 
152 
153 
main(int,char **)154 int main(int /*ac*/, char** /*av*/)
155 {
156    test_ambiguous();
157    test_unknown_option();
158    test_multiple_values();
159    test_multiple_occurrences();
160    test_missing_value();
161 
162    return 0;
163 }
164 
165