• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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