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>
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
22void 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(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
36 argv: const_cast<char**>(cmdline), desc), m&: 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
48void test_ambiguous_long()
49{
50 options_description desc;
51 desc.add_options()
52 ("cfgfile,c", value<string>()->multitoken(), "the config file")
53 ("output,c", value<string>(), "the output file")
54 ("output,o", value<string>(), "the output file")
55 ;
56
57 const char* cmdline[] = {"program", "--cfgfile", "file", "--output", "anotherfile"};
58
59 variables_map vm;
60 try {
61 store(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
62 argv: const_cast<char**>(cmdline), desc), m&: vm);
63 }
64 catch (ambiguous_option& e)
65 {
66 BOOST_CHECK_EQUAL(e.alternatives().size(), 2);
67 BOOST_CHECK_EQUAL(e.get_option_name(), "--output");
68 BOOST_CHECK_EQUAL(e.alternatives()[0], "output");
69 BOOST_CHECK_EQUAL(e.alternatives()[1], "output");
70 }
71}
72
73void test_ambiguous_multiple_long_names()
74{
75 options_description desc;
76 desc.add_options()
77 ("cfgfile,foo,c", value<string>()->multitoken(), "the config file")
78 ("output,foo,o", value<string>(), "the output file")
79 ;
80
81 const char* cmdline[] = {"program", "--foo", "file"};
82
83 variables_map vm;
84 try {
85 store(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
86 argv: const_cast<char**>(cmdline), desc), m&: vm);
87 }
88 catch (ambiguous_option& e)
89 {
90 BOOST_CHECK_EQUAL(e.alternatives().size(), 2);
91 BOOST_CHECK_EQUAL(e.get_option_name(), "--foo");
92 BOOST_CHECK_EQUAL(e.alternatives()[0], "cfgfile");
93 BOOST_CHECK_EQUAL(e.alternatives()[1], "output");
94 }
95}
96
97
98
99void test_unknown_option()
100{
101 options_description desc;
102 desc.add_options()
103 ("cfgfile,c", value<string>(), "the configfile")
104 ;
105
106 const char* cmdline[] = {"program", "-c", "file", "-f", "anotherfile"};
107
108 variables_map vm;
109 try {
110 store(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
111 argv: const_cast<char**>(cmdline), desc), m&: vm);
112 }
113 catch (unknown_option& e)
114 {
115 BOOST_CHECK_EQUAL(e.get_option_name(), "-f");
116 BOOST_CHECK_EQUAL(string(e.what()), "unrecognised option '-f'");
117 }
118}
119
120
121
122void test_multiple_values()
123{
124 options_description desc;
125 desc.add_options()
126 ("cfgfile,c", value<string>()->multitoken(), "the config file")
127 ("output,o", value<string>(), "the output file")
128 ;
129
130 const char* cmdline[] = { "program", "-o", "fritz", "hugo", "--cfgfile", "file", "c", "-o", "text.out" };
131
132 variables_map vm;
133 try {
134 store(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
135 argv: const_cast<char**>(cmdline), desc), m&: vm);
136 notify(m&: vm);
137 }
138 catch (validation_error& e)
139 {
140 // TODO: this is currently validation_error, shouldn't it be multiple_values ???
141 //
142 // multiple_values is thrown only at one place untyped_value::xparse(),
143 // but I think this can never be reached
144 // because: untyped_value always has one value and this is filtered before reach specific
145 // validation and parsing
146 //
147 BOOST_CHECK_EQUAL(e.get_option_name(), "--cfgfile");
148 BOOST_CHECK_EQUAL(string(e.what()), "option '--cfgfile' only takes a single argument");
149 }
150}
151
152
153void test_multiple_occurrences()
154{
155 options_description desc;
156 desc.add_options()
157 ("cfgfile,c", value<string>(), "the configfile")
158 ;
159
160 const char* cmdline[] = {"program", "--cfgfile", "file", "-c", "anotherfile"};
161
162 variables_map vm;
163 try {
164 store(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
165 argv: const_cast<char**>(cmdline), desc), m&: vm);
166 notify(m&: vm);
167 }
168 catch (multiple_occurrences& e)
169 {
170 BOOST_CHECK_EQUAL(e.get_option_name(), "--cfgfile");
171 BOOST_CHECK_EQUAL(string(e.what()), "option '--cfgfile' cannot be specified more than once");
172 }
173}
174
175void test_multiple_occurrences_with_different_names()
176{
177 options_description desc;
178 desc.add_options()
179 ("cfgfile,config-file,c", value<string>(), "the configfile")
180 ;
181
182 const char* cmdline[] = {"program", "--config-file", "file", "--cfgfile", "anotherfile"};
183
184 variables_map vm;
185 try {
186 store(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
187 argv: const_cast<char**>(cmdline), desc), m&: vm);
188 notify(m&: vm);
189 }
190 catch (multiple_occurrences& e)
191 {
192 BOOST_CHECK( (e.get_option_name() == "--cfgfile") || (e.get_option_name() == "--config-file"));
193 BOOST_CHECK(
194 (string(e.what()) == "option '--cfgfile' cannot be specified more than once") ||
195 (string(e.what()) == "option '--config-file' cannot be specified more than once")
196 );
197 }
198}
199
200
201void test_multiple_occurrences_with_non_key_names()
202{
203 options_description desc;
204 desc.add_options()
205 ("cfgfile,config-file,c", value<string>(), "the configfile")
206 ;
207
208 const char* cmdline[] = {"program", "--config-file", "file", "-c", "anotherfile"};
209
210 variables_map vm;
211 try {
212 store(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
213 argv: const_cast<char**>(cmdline), desc), m&: vm);
214 notify(m&: vm);
215 }
216 catch (multiple_occurrences& e)
217 {
218 BOOST_CHECK_EQUAL(e.get_option_name(), "--cfgfile");
219 BOOST_CHECK_EQUAL(string(e.what()), "option '--cfgfile' cannot be specified more than once");
220 }
221}
222
223
224void test_missing_value()
225{
226 options_description desc;
227 desc.add_options()
228 ("cfgfile,c", value<string>()->multitoken(), "the config file")
229 ("output,o", value<string>(), "the output file")
230 ;
231 // missing value for option '-c'
232 const char* cmdline[] = { "program", "-c", "-c", "output.txt"};
233
234 variables_map vm;
235
236 try {
237 store(options: parse_command_line(argc: sizeof(cmdline)/sizeof(const char*),
238 argv: const_cast<char**>(cmdline), desc), m&: vm);
239 notify(m&: vm);
240 }
241 catch (invalid_command_line_syntax& e)
242 {
243 BOOST_CHECK_EQUAL(e.kind(), invalid_syntax::missing_parameter);
244 BOOST_CHECK_EQUAL(e.tokens(), "--cfgfile");
245 }
246}
247
248
249
250int main(int /*ac*/, char** /*av*/)
251{
252 test_ambiguous();
253 test_ambiguous_long();
254 test_ambiguous_multiple_long_names();
255 test_unknown_option();
256 test_multiple_values();
257 test_multiple_occurrences();
258 test_multiple_occurrences_with_different_names();
259 test_multiple_occurrences_with_non_key_names();
260 test_missing_value();
261
262 return 0;
263}
264
265

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