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
7 #include <boost/program_options/options_description.hpp>
8 using namespace boost::program_options;
9
10 #include <boost/function.hpp>
11 using namespace boost;
12
13 #include <utility>
14 #include <string>
15 #include <sstream>
16 using namespace std;
17
18 #include "minitest.hpp"
19
test_type()20 void test_type()
21 {
22 options_description desc;
23 desc.add_options()
24 ("foo", value<int>(), "")
25 ("bar", value<string>(), "")
26 ;
27
28 #ifndef BOOST_NO_RTTI
29 const typed_value_base* b = dynamic_cast<const typed_value_base*>
30 (desc.find("foo", false).semantic().get());
31 BOOST_CHECK(b);
32 BOOST_CHECK(b->value_type() == typeid(int));
33
34 const typed_value_base* b2 = dynamic_cast<const typed_value_base*>
35 (desc.find("bar", false).semantic().get());
36 BOOST_CHECK(b2);
37 BOOST_CHECK(b2->value_type() == typeid(string));
38 #endif
39 }
40
test_approximation()41 void test_approximation()
42 {
43 options_description desc;
44 desc.add_options()
45 ("foo", new untyped_value())
46 ("fee", new untyped_value())
47 ("baz", new untyped_value())
48 ("all-chroots", new untyped_value())
49 ("all-sessions", new untyped_value())
50 ("all", new untyped_value())
51 ;
52
53 BOOST_CHECK_EQUAL(desc.find("fo", true).long_name(), "foo");
54
55 BOOST_CHECK_EQUAL(desc.find("all", true).long_name(), "all");
56 BOOST_CHECK_EQUAL(desc.find("all-ch", true).long_name(), "all-chroots");
57
58 options_description desc2;
59 desc2.add_options()
60 ("help", "display this message")
61 ("config", value<string>(), "config file name")
62 ("config-value", value<string>(), "single config value")
63 ;
64
65 BOOST_CHECK_EQUAL(desc2.find("config", true).long_name(), "config");
66 BOOST_CHECK_EQUAL(desc2.find("config-value", true).long_name(),
67 "config-value");
68
69
70 // BOOST_CHECK(desc.count_approx("foo") == 1);
71 // set<string> a = desc.approximations("f");
72 // BOOST_CHECK(a.size() == 2);
73 // BOOST_CHECK(*a.begin() == "fee");
74 // BOOST_CHECK(*(++a.begin()) == "foo");
75 }
76
test_approximation_with_multiname_options()77 void test_approximation_with_multiname_options()
78 {
79 options_description desc;
80 desc.add_options()
81 ("foo", new untyped_value())
82 ("fee", new untyped_value())
83 ("fe,baz", new untyped_value())
84 ("chroots,all-chroots", new untyped_value())
85 ("sessions,all-sessions", new untyped_value())
86 ("everything,all", new untyped_value())
87 ("qux,fo", new untyped_value())
88 ;
89
90 BOOST_CHECK_EQUAL(desc.find("fo", true).long_name(), "qux");
91
92 BOOST_CHECK_EQUAL(desc.find("all", true).long_name(), "everything");
93 BOOST_CHECK_EQUAL(desc.find("all-ch", true).long_name(), "chroots");
94
95 BOOST_CHECK_EQUAL(desc.find("foo", false, false, false).long_names().second, 1u);
96 BOOST_CHECK_EQUAL(desc.find("foo", false, false, false).long_names().first[0], "foo");
97
98 BOOST_CHECK_EQUAL(desc.find("fe", false, false, false).long_names().second, 2u);
99 BOOST_CHECK_EQUAL(desc.find("fe", false, false, false).long_names().first[0], "fe");
100 BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().first[1], "baz");
101
102 BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().second, 2u);
103 BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().first[0], "fizbaz");
104 BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().first[1], "baz");
105 }
106
test_long_names_for_option_description()107 void test_long_names_for_option_description()
108 {
109 options_description desc;
110 desc.add_options()
111 ("foo", new untyped_value())
112 ("fe,baz", new untyped_value())
113 ("chroots,all-chroots", new untyped_value())
114 ("sessions,all-sessions", new untyped_value())
115 ("everything,all", new untyped_value())
116 ("qux,fo,q", new untyped_value())
117 ;
118
119 BOOST_CHECK_EQUAL(desc.find("foo", false, false, false).long_names().second, 1u);
120 BOOST_CHECK_EQUAL(desc.find("foo", false, false, false).long_names().first[0], "foo");
121
122 BOOST_CHECK_EQUAL(desc.find("fe", false, false, false).long_names().second, 2u);
123 BOOST_CHECK_EQUAL(desc.find("fe", false, false, false).long_names().first[0], "fe");
124 BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().first[1], "baz");
125
126 BOOST_CHECK_EQUAL(desc.find("qux", false, false, false).long_names().second, 2u);
127 BOOST_CHECK_EQUAL(desc.find("qux", false, false, false).long_names().first[0], "qux");
128 BOOST_CHECK_EQUAL(desc.find("qux", false, false, false).long_names().first[1], "fo");
129 }
130
131
test_formatting()132 void test_formatting()
133 {
134 // Long option descriptions used to crash on MSVC-8.0.
135 options_description desc;
136 desc.add_options()(
137 "test", new untyped_value(),
138 "foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
139 "foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
140 "foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
141 "foo foo foo foo foo foo foo foo foo foo foo foo foo foo")
142 ("list", new untyped_value(),
143 "a list:\n \t"
144 "item1, item2, item3, item4, item5, item6, item7, item8, item9, "
145 "item10, item11, item12, item13, item14, item15, item16, item17, item18")
146 ("well_formated", new untyped_value(),
147 "As you can see this is a very well formatted option description.\n"
148 "You can do this for example:\n\n"
149 "Values:\n"
150 " Value1: \tdoes this and that, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n"
151 " Value2: \tdoes something else, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n\n"
152 " This paragraph has a first line indent only, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla")
153 ;
154
155 stringstream ss;
156 ss << desc;
157 BOOST_CHECK_EQUAL(ss.str(),
158 " --test arg foo foo foo foo foo foo foo foo foo foo foo foo foo \n"
159 " foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
160 " foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
161 " foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
162 " foo\n"
163 " --list arg a list:\n"
164 " item1, item2, item3, item4, item5, item6, item7, \n"
165 " item8, item9, item10, item11, item12, item13, \n"
166 " item14, item15, item16, item17, item18\n"
167 " --well_formated arg As you can see this is a very well formatted option \n"
168 " description.\n"
169 " You can do this for example:\n"
170 " \n"
171 " Values:\n"
172 " Value1: does this and that, bla bla bla bla bla bla \n"
173 " bla bla bla bla bla bla bla bla bla\n"
174 " Value2: does something else, bla bla bla bla bla bla \n"
175 " bla bla bla bla bla bla bla bla bla\n"
176 " \n"
177 " This paragraph has a first line indent only, bla \n"
178 " bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n"
179 );
180 }
181
test_multiname_option_formatting()182 void test_multiname_option_formatting()
183 {
184 options_description desc;
185 desc.add_options()
186 ("foo,bar", new untyped_value(), "a multiple-name option")
187 ;
188
189 stringstream ss;
190 ss << desc;
191 BOOST_CHECK_EQUAL(ss.str(),
192 " --foo arg a multiple-name option\n"
193 );
194 }
195
196
test_formatting_description_length()197 void test_formatting_description_length()
198 {
199 {
200 options_description desc("",
201 options_description::m_default_line_length,
202 options_description::m_default_line_length / 2U);
203 desc.add_options()
204 ("an-option-that-sets-the-max", new untyped_value(), // > 40 available for desc
205 "this description sits on the same line, but wrapping should still work correctly")
206 ("a-long-option-that-would-leave-very-little-space-for-description", new untyped_value(),
207 "the description of the long opt, but placed on the next line\n"
208 " \talso ensure that the tabulation works correctly when a"
209 " description size has been set");
210
211 stringstream ss;
212 ss << desc;
213 BOOST_CHECK_EQUAL(ss.str(),
214 " --an-option-that-sets-the-max arg this description sits on the same line,\n"
215 " but wrapping should still work \n"
216 " correctly\n"
217 " --a-long-option-that-would-leave-very-little-space-for-description arg\n"
218 " the description of the long opt, but \n"
219 " placed on the next line\n"
220 " also ensure that the tabulation \n"
221 " works correctly when a description \n"
222 " size has been set\n");
223 }
224 {
225 // the default behaviour reserves 23 (+1 space) characters for the
226 // option column; this shows that the min_description_length does not
227 // breach that.
228 options_description desc("",
229 options_description::m_default_line_length,
230 options_description::m_default_line_length - 10U); // leaves < 23 (default option space)
231 desc.add_options()
232 ("an-option-that-encroaches-description", new untyped_value(),
233 "this description should always be placed on the next line, and wrapping should continue as normal");
234
235 stringstream ss;
236 ss << desc;
237 BOOST_CHECK_EQUAL(ss.str(),
238 " --an-option-that-encroaches-description arg\n"
239 //123456789_123456789_
240 " this description should always be placed on the next line, and \n"
241 " wrapping should continue as normal\n");
242 }
243 }
244
test_long_default_value()245 void test_long_default_value()
246 {
247 options_description desc;
248 desc.add_options()
249 ("cfgfile,c",
250 value<string>()->default_value("/usr/local/etc/myprogramXXXXXXXXX/configuration.conf"),
251 "the configfile")
252 ;
253
254 stringstream ss;
255 ss << desc;
256 BOOST_CHECK_EQUAL(ss.str(),
257 " -c [ --cfgfile ] arg (=/usr/local/etc/myprogramXXXXXXXXX/configuration.conf)\n"
258 " the configfile\n"
259 );
260 }
261
test_word_wrapping()262 void test_word_wrapping()
263 {
264 options_description desc("Supported options");
265 desc.add_options()
266 ("help", "this is a sufficiently long text to require word-wrapping")
267 ("prefix", value<string>()->default_value("/h/proj/tmp/dispatch"), "root path of the dispatch installation")
268 ("opt1", "this_is_a_sufficiently_long_text_to_require_word-wrapping_but_cannot_be_wrapped")
269 ("opt2", "this_is_a_sufficiently long_text_to_require_word-wrapping")
270 ("opt3", "this_is_a sufficiently_long_text_to_require_word-wrapping_but_will_not_be_wrapped")
271 ;
272 stringstream ss;
273 ss << desc;
274 BOOST_CHECK_EQUAL(ss.str(),
275 "Supported options:\n"
276 " --help this is a sufficiently long text to \n"
277 " require word-wrapping\n"
278 " --prefix arg (=/h/proj/tmp/dispatch) root path of the dispatch installation\n"
279 " --opt1 this_is_a_sufficiently_long_text_to_requ\n"
280 " ire_word-wrapping_but_cannot_be_wrapped\n"
281 " --opt2 this_is_a_sufficiently \n"
282 " long_text_to_require_word-wrapping\n"
283 " --opt3 this_is_a sufficiently_long_text_to_requ\n"
284 " ire_word-wrapping_but_will_not_be_wrappe\n"
285 " d\n"
286 );
287 }
288
test_default_values()289 void test_default_values()
290 {
291 options_description desc("Supported options");
292 desc.add_options()
293 ("maxlength", value<double>()->default_value(.1, "0.1"), "Maximum edge length to keep.")
294 ;
295 stringstream ss;
296 ss << desc;
297 BOOST_CHECK_EQUAL(ss.str(),
298 "Supported options:\n"
299 " --maxlength arg (=0.1) Maximum edge length to keep.\n"
300 );
301 }
302
test_value_name()303 void test_value_name()
304 {
305 options_description desc("Supported options");
306 desc.add_options()
307 ("include", value<string>()->value_name("directory"), "Search for headers in 'directory'.")
308 ;
309
310 stringstream ss;
311 ss << desc;
312 BOOST_CHECK_EQUAL(ss.str(),
313 "Supported options:\n"
314 " --include directory Search for headers in 'directory'.\n"
315 );
316 }
317
test_multiname_key_and_switch_selection()318 void test_multiname_key_and_switch_selection()
319 {
320 // cases:
321 // foo,f -> f
322 // foo, c -> c
323 // foo,f,g -> g
324 // f,g,h -> h
325 // f,foo throws
326 // foo,bar -> no switch
327 // foo,f,bar -> no switch
328
329 // what about empty strings - consecutive ,'s ?
330 }
331
main(int,char * [])332 int main(int, char* [])
333 {
334 test_type();
335 test_approximation();
336 test_long_names_for_option_description();
337 test_formatting();
338 test_multiname_key_and_switch_selection();
339 test_multiname_option_formatting();
340 test_formatting_description_length();
341 test_long_default_value();
342 test_word_wrapping();
343 test_default_values();
344 test_value_name();
345 return 0;
346 }
347
348