xref: /minix3/external/bsd/kyua-cli/dist/utils/cmdline/parser_test.cpp (revision 11be35a165022172ed3cea20f2b5df0307540b0e)
1*11be35a1SLionel Sambuc // Copyright 2010 Google Inc.
2*11be35a1SLionel Sambuc // All rights reserved.
3*11be35a1SLionel Sambuc //
4*11be35a1SLionel Sambuc // Redistribution and use in source and binary forms, with or without
5*11be35a1SLionel Sambuc // modification, are permitted provided that the following conditions are
6*11be35a1SLionel Sambuc // met:
7*11be35a1SLionel Sambuc //
8*11be35a1SLionel Sambuc // * Redistributions of source code must retain the above copyright
9*11be35a1SLionel Sambuc //   notice, this list of conditions and the following disclaimer.
10*11be35a1SLionel Sambuc // * Redistributions in binary form must reproduce the above copyright
11*11be35a1SLionel Sambuc //   notice, this list of conditions and the following disclaimer in the
12*11be35a1SLionel Sambuc //   documentation and/or other materials provided with the distribution.
13*11be35a1SLionel Sambuc // * Neither the name of Google Inc. nor the names of its contributors
14*11be35a1SLionel Sambuc //   may be used to endorse or promote products derived from this software
15*11be35a1SLionel Sambuc //   without specific prior written permission.
16*11be35a1SLionel Sambuc //
17*11be35a1SLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*11be35a1SLionel Sambuc // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*11be35a1SLionel Sambuc // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*11be35a1SLionel Sambuc // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*11be35a1SLionel Sambuc // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*11be35a1SLionel Sambuc // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*11be35a1SLionel Sambuc // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*11be35a1SLionel Sambuc // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*11be35a1SLionel Sambuc // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*11be35a1SLionel Sambuc // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*11be35a1SLionel Sambuc // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*11be35a1SLionel Sambuc 
29*11be35a1SLionel Sambuc #include "utils/cmdline/parser.ipp"
30*11be35a1SLionel Sambuc 
31*11be35a1SLionel Sambuc #if defined(HAVE_CONFIG_H)
32*11be35a1SLionel Sambuc #include "config.h"
33*11be35a1SLionel Sambuc #endif
34*11be35a1SLionel Sambuc 
35*11be35a1SLionel Sambuc extern "C" {
36*11be35a1SLionel Sambuc #include <fcntl.h>
37*11be35a1SLionel Sambuc #include <getopt.h>
38*11be35a1SLionel Sambuc #include <unistd.h>
39*11be35a1SLionel Sambuc }
40*11be35a1SLionel Sambuc 
41*11be35a1SLionel Sambuc #include <cstdlib>
42*11be35a1SLionel Sambuc #include <cstring>
43*11be35a1SLionel Sambuc #include <fstream>
44*11be35a1SLionel Sambuc #include <iostream>
45*11be35a1SLionel Sambuc #include <string>
46*11be35a1SLionel Sambuc #include <utility>
47*11be35a1SLionel Sambuc 
48*11be35a1SLionel Sambuc #include <atf-c++.hpp>
49*11be35a1SLionel Sambuc 
50*11be35a1SLionel Sambuc #include "utils/cmdline/exceptions.hpp"
51*11be35a1SLionel Sambuc #include "utils/cmdline/options.hpp"
52*11be35a1SLionel Sambuc #include "utils/format/macros.hpp"
53*11be35a1SLionel Sambuc #include "utils/sanity.hpp"
54*11be35a1SLionel Sambuc 
55*11be35a1SLionel Sambuc namespace cmdline = utils::cmdline;
56*11be35a1SLionel Sambuc 
57*11be35a1SLionel Sambuc using cmdline::base_option;
58*11be35a1SLionel Sambuc using cmdline::bool_option;
59*11be35a1SLionel Sambuc using cmdline::int_option;
60*11be35a1SLionel Sambuc using cmdline::parse;
61*11be35a1SLionel Sambuc using cmdline::parsed_cmdline;
62*11be35a1SLionel Sambuc using cmdline::string_option;
63*11be35a1SLionel Sambuc 
64*11be35a1SLionel Sambuc 
65*11be35a1SLionel Sambuc namespace {
66*11be35a1SLionel Sambuc 
67*11be35a1SLionel Sambuc 
68*11be35a1SLionel Sambuc /// Mock option type to check the validate and convert methods sequence.
69*11be35a1SLionel Sambuc ///
70*11be35a1SLionel Sambuc /// Instances of this option accept a string argument that must be either "zero"
71*11be35a1SLionel Sambuc /// or "one".  These are validated and converted to integers.
72*11be35a1SLionel Sambuc class mock_option : public base_option {
73*11be35a1SLionel Sambuc public:
74*11be35a1SLionel Sambuc     /// Constructs the new option.
75*11be35a1SLionel Sambuc     ///
76*11be35a1SLionel Sambuc     /// \param long_name_ The long name for the option.  All other option
77*11be35a1SLionel Sambuc     ///     properties are irrelevant for the tests using this, so they are set
78*11be35a1SLionel Sambuc     ///     to arbitrary values.
mock_option(const char * long_name_)79*11be35a1SLionel Sambuc     mock_option(const char* long_name_) :
80*11be35a1SLionel Sambuc         base_option(long_name_, "Irrelevant description", "arg")
81*11be35a1SLionel Sambuc     {
82*11be35a1SLionel Sambuc     }
83*11be35a1SLionel Sambuc 
84*11be35a1SLionel Sambuc     /// The type of the argument of this option.
85*11be35a1SLionel Sambuc     typedef int option_type;
86*11be35a1SLionel Sambuc 
87*11be35a1SLionel Sambuc     /// Checks that the user-provided option is valid.
88*11be35a1SLionel Sambuc     ///
89*11be35a1SLionel Sambuc     /// \param str The user argument; must be "zero" or "one".
90*11be35a1SLionel Sambuc     ///
91*11be35a1SLionel Sambuc     /// \throw cmdline::option_argument_value_error If str is not valid.
92*11be35a1SLionel Sambuc     void
validate(const std::string & str) const93*11be35a1SLionel Sambuc     validate(const std::string& str) const
94*11be35a1SLionel Sambuc     {
95*11be35a1SLionel Sambuc         if (str != "zero" && str != "one")
96*11be35a1SLionel Sambuc             throw cmdline::option_argument_value_error(F("--%s") % long_name(),
97*11be35a1SLionel Sambuc                                                        str, "Unknown value");
98*11be35a1SLionel Sambuc     }
99*11be35a1SLionel Sambuc 
100*11be35a1SLionel Sambuc     /// Converts the user-provided argument to our native integer type.
101*11be35a1SLionel Sambuc     ///
102*11be35a1SLionel Sambuc     /// \param str The user argument; must be "zero" or "one".
103*11be35a1SLionel Sambuc     ///
104*11be35a1SLionel Sambuc     /// \return 0 if the input is "zero", or 1 if the input is "one".
105*11be35a1SLionel Sambuc     ///
106*11be35a1SLionel Sambuc     /// \throw std::runtime_error If str is not valid.  In real life, this
107*11be35a1SLionel Sambuc     ///     should be a precondition because validate() has already ensured that
108*11be35a1SLionel Sambuc     ///     the values passed to convert() are correct.  However, we raise an
109*11be35a1SLionel Sambuc     ///     exception here because we are actually validating that this code
110*11be35a1SLionel Sambuc     ///     sequence holds true.
111*11be35a1SLionel Sambuc     static int
convert(const std::string & str)112*11be35a1SLionel Sambuc     convert(const std::string& str)
113*11be35a1SLionel Sambuc     {
114*11be35a1SLionel Sambuc         if (str == "zero")
115*11be35a1SLionel Sambuc             return 0;
116*11be35a1SLionel Sambuc         else if (str == "one")
117*11be35a1SLionel Sambuc             return 1;
118*11be35a1SLionel Sambuc         else {
119*11be35a1SLionel Sambuc             // This would generally be an assertion but, given that this is
120*11be35a1SLionel Sambuc             // test code, we want to catch any errors regardless of how the
121*11be35a1SLionel Sambuc             // binary is built.
122*11be35a1SLionel Sambuc             throw std::runtime_error("Value not validated properly.");
123*11be35a1SLionel Sambuc         }
124*11be35a1SLionel Sambuc     }
125*11be35a1SLionel Sambuc };
126*11be35a1SLionel Sambuc 
127*11be35a1SLionel Sambuc 
128*11be35a1SLionel Sambuc /// Redirects stdout and stderr to a file.
129*11be35a1SLionel Sambuc ///
130*11be35a1SLionel Sambuc /// This fails the test case in case of any error.
131*11be35a1SLionel Sambuc ///
132*11be35a1SLionel Sambuc /// \param file The name of the file to redirect stdout and stderr to.
133*11be35a1SLionel Sambuc ///
134*11be35a1SLionel Sambuc /// \return A copy of the old stdout and stderr file descriptors.
135*11be35a1SLionel Sambuc static std::pair< int, int >
mock_stdfds(const char * file)136*11be35a1SLionel Sambuc mock_stdfds(const char* file)
137*11be35a1SLionel Sambuc {
138*11be35a1SLionel Sambuc     std::cout.flush();
139*11be35a1SLionel Sambuc     std::cerr.flush();
140*11be35a1SLionel Sambuc 
141*11be35a1SLionel Sambuc     const int oldout = ::dup(STDOUT_FILENO);
142*11be35a1SLionel Sambuc     ATF_REQUIRE(oldout != -1);
143*11be35a1SLionel Sambuc     const int olderr = ::dup(STDERR_FILENO);
144*11be35a1SLionel Sambuc     ATF_REQUIRE(olderr != -1);
145*11be35a1SLionel Sambuc 
146*11be35a1SLionel Sambuc     const int fd = ::open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
147*11be35a1SLionel Sambuc     ATF_REQUIRE(fd != -1);
148*11be35a1SLionel Sambuc     ATF_REQUIRE(::dup2(fd, STDOUT_FILENO) != -1);
149*11be35a1SLionel Sambuc     ATF_REQUIRE(::dup2(fd, STDERR_FILENO) != -1);
150*11be35a1SLionel Sambuc     ::close(fd);
151*11be35a1SLionel Sambuc 
152*11be35a1SLionel Sambuc     return std::make_pair(oldout, olderr);
153*11be35a1SLionel Sambuc }
154*11be35a1SLionel Sambuc 
155*11be35a1SLionel Sambuc 
156*11be35a1SLionel Sambuc /// Restores stdout and stderr after a call to mock_stdfds.
157*11be35a1SLionel Sambuc ///
158*11be35a1SLionel Sambuc /// \param oldfds The copy of the previous stdout and stderr as returned by the
159*11be35a1SLionel Sambuc ///     call to mock_fds().
160*11be35a1SLionel Sambuc static void
restore_stdfds(const std::pair<int,int> & oldfds)161*11be35a1SLionel Sambuc restore_stdfds(const std::pair< int, int >& oldfds)
162*11be35a1SLionel Sambuc {
163*11be35a1SLionel Sambuc     ATF_REQUIRE(::dup2(oldfds.first, STDOUT_FILENO) != -1);
164*11be35a1SLionel Sambuc     ::close(oldfds.first);
165*11be35a1SLionel Sambuc     ATF_REQUIRE(::dup2(oldfds.second, STDERR_FILENO) != -1);
166*11be35a1SLionel Sambuc     ::close(oldfds.second);
167*11be35a1SLionel Sambuc }
168*11be35a1SLionel Sambuc 
169*11be35a1SLionel Sambuc 
170*11be35a1SLionel Sambuc /// Checks whether a '+:' prefix to the short options of getopt_long works.
171*11be35a1SLionel Sambuc ///
172*11be35a1SLionel Sambuc /// It turns out that the getopt_long(3) implementation of Ubuntu 10.04.1 (and
173*11be35a1SLionel Sambuc /// very likely other distributions) does not properly report a missing argument
174*11be35a1SLionel Sambuc /// to a second long option as such.  Instead of returning ':' when the second
175*11be35a1SLionel Sambuc /// long option provided on the command line does not carry a required argument,
176*11be35a1SLionel Sambuc /// it will mistakenly return '?' which translates to "unknown option".
177*11be35a1SLionel Sambuc ///
178*11be35a1SLionel Sambuc /// As a result of this bug, we cannot properly detect that 'flag2' requires an
179*11be35a1SLionel Sambuc /// argument in a command line like: 'progname --flag1=foo --flag2'.
180*11be35a1SLionel Sambuc ///
181*11be35a1SLionel Sambuc /// I am not sure if we could fully workaround the issue in the implementation
182*11be35a1SLionel Sambuc /// of our library.  For the time being I am just using this bug detection in
183*11be35a1SLionel Sambuc /// the test cases to prevent failures that are not really our fault.
184*11be35a1SLionel Sambuc ///
185*11be35a1SLionel Sambuc /// \return bool True if getopt_long is broken and does not interpret '+:'
186*11be35a1SLionel Sambuc ///     correctly; False otherwise.
187*11be35a1SLionel Sambuc static bool
is_getopt_long_pluscolon_broken(void)188*11be35a1SLionel Sambuc is_getopt_long_pluscolon_broken(void)
189*11be35a1SLionel Sambuc {
190*11be35a1SLionel Sambuc     struct ::option long_options[] = {
191*11be35a1SLionel Sambuc         { "flag1", 1, NULL, '1' },
192*11be35a1SLionel Sambuc         { "flag2", 1, NULL, '2' },
193*11be35a1SLionel Sambuc         { NULL, 0, NULL, 0 }
194*11be35a1SLionel Sambuc     };
195*11be35a1SLionel Sambuc 
196*11be35a1SLionel Sambuc     const int argc = 3;
197*11be35a1SLionel Sambuc     char* argv[4];
198*11be35a1SLionel Sambuc     argv[0] = ::strdup("progname");
199*11be35a1SLionel Sambuc     argv[1] = ::strdup("--flag1=a");
200*11be35a1SLionel Sambuc     argv[2] = ::strdup("--flag2");
201*11be35a1SLionel Sambuc     argv[3] = NULL;
202*11be35a1SLionel Sambuc 
203*11be35a1SLionel Sambuc     const int old_opterr = ::opterr;
204*11be35a1SLionel Sambuc     ::opterr = 0;
205*11be35a1SLionel Sambuc 
206*11be35a1SLionel Sambuc     bool got_colon = false;
207*11be35a1SLionel Sambuc 
208*11be35a1SLionel Sambuc     int opt;
209*11be35a1SLionel Sambuc     while ((opt = ::getopt_long(argc, argv, "+:", long_options, NULL)) != -1) {
210*11be35a1SLionel Sambuc         switch (opt) {
211*11be35a1SLionel Sambuc         case '1': break;
212*11be35a1SLionel Sambuc         case '2': break;
213*11be35a1SLionel Sambuc         case ':': got_colon = true; break;
214*11be35a1SLionel Sambuc         case '?': break;
215*11be35a1SLionel Sambuc         default:  UNREACHABLE; break;
216*11be35a1SLionel Sambuc         }
217*11be35a1SLionel Sambuc     }
218*11be35a1SLionel Sambuc 
219*11be35a1SLionel Sambuc     ::opterr = old_opterr;
220*11be35a1SLionel Sambuc     ::optind = 1;
221*11be35a1SLionel Sambuc #if defined(HAVE_GETOPT_WITH_OPTRESET)
222*11be35a1SLionel Sambuc     ::optreset = 1;
223*11be35a1SLionel Sambuc #endif
224*11be35a1SLionel Sambuc 
225*11be35a1SLionel Sambuc     for (char** arg = &argv[0]; *arg != NULL; arg++)
226*11be35a1SLionel Sambuc         std::free(*arg);
227*11be35a1SLionel Sambuc 
228*11be35a1SLionel Sambuc     return !got_colon;
229*11be35a1SLionel Sambuc }
230*11be35a1SLionel Sambuc 
231*11be35a1SLionel Sambuc 
232*11be35a1SLionel Sambuc }  // anonymous namespace
233*11be35a1SLionel Sambuc 
234*11be35a1SLionel Sambuc 
235*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(progname__no_options);
ATF_TEST_CASE_BODY(progname__no_options)236*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(progname__no_options)
237*11be35a1SLionel Sambuc {
238*11be35a1SLionel Sambuc     const int argc = 1;
239*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", NULL};
240*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
241*11be35a1SLionel Sambuc     const parsed_cmdline cmdline = parse(argc, argv, options);
242*11be35a1SLionel Sambuc 
243*11be35a1SLionel Sambuc     ATF_REQUIRE(cmdline.arguments().empty());
244*11be35a1SLionel Sambuc }
245*11be35a1SLionel Sambuc 
246*11be35a1SLionel Sambuc 
247*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(progname__some_options);
ATF_TEST_CASE_BODY(progname__some_options)248*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(progname__some_options)
249*11be35a1SLionel Sambuc {
250*11be35a1SLionel Sambuc     const int argc = 1;
251*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", NULL};
252*11be35a1SLionel Sambuc     const string_option a('a', "a_option", "Foo", NULL);
253*11be35a1SLionel Sambuc     const string_option b('b', "b_option", "Bar", "arg", "foo");
254*11be35a1SLionel Sambuc     const string_option c("c_option", "Baz", NULL);
255*11be35a1SLionel Sambuc     const string_option d("d_option", "Wohoo", "arg", "bar");
256*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
257*11be35a1SLionel Sambuc     options.push_back(&a);
258*11be35a1SLionel Sambuc     options.push_back(&b);
259*11be35a1SLionel Sambuc     options.push_back(&c);
260*11be35a1SLionel Sambuc     options.push_back(&d);
261*11be35a1SLionel Sambuc     const parsed_cmdline cmdline = parse(argc, argv, options);
262*11be35a1SLionel Sambuc 
263*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("foo", cmdline.get_option< string_option >("b_option"));
264*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("bar", cmdline.get_option< string_option >("d_option"));
265*11be35a1SLionel Sambuc     ATF_REQUIRE(cmdline.arguments().empty());
266*11be35a1SLionel Sambuc }
267*11be35a1SLionel Sambuc 
268*11be35a1SLionel Sambuc 
269*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(some_args__no_options);
ATF_TEST_CASE_BODY(some_args__no_options)270*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(some_args__no_options)
271*11be35a1SLionel Sambuc {
272*11be35a1SLionel Sambuc     const int argc = 5;
273*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "foo", "-c", "--opt", "bar", NULL};
274*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
275*11be35a1SLionel Sambuc     const parsed_cmdline cmdline = parse(argc, argv, options);
276*11be35a1SLionel Sambuc 
277*11be35a1SLionel Sambuc     ATF_REQUIRE(!cmdline.has_option("c"));
278*11be35a1SLionel Sambuc     ATF_REQUIRE(!cmdline.has_option("opt"));
279*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ(4, cmdline.arguments().size());
280*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("foo", cmdline.arguments()[0]);
281*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("-c", cmdline.arguments()[1]);
282*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("--opt", cmdline.arguments()[2]);
283*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("bar", cmdline.arguments()[3]);
284*11be35a1SLionel Sambuc }
285*11be35a1SLionel Sambuc 
286*11be35a1SLionel Sambuc 
287*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(some_args__some_options);
ATF_TEST_CASE_BODY(some_args__some_options)288*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(some_args__some_options)
289*11be35a1SLionel Sambuc {
290*11be35a1SLionel Sambuc     const int argc = 5;
291*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "foo", "-c", "--opt", "bar", NULL};
292*11be35a1SLionel Sambuc     const string_option c('c', "opt", "Description", NULL);
293*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
294*11be35a1SLionel Sambuc     options.push_back(&c);
295*11be35a1SLionel Sambuc     const parsed_cmdline cmdline = parse(argc, argv, options);
296*11be35a1SLionel Sambuc 
297*11be35a1SLionel Sambuc     ATF_REQUIRE(!cmdline.has_option("c"));
298*11be35a1SLionel Sambuc     ATF_REQUIRE(!cmdline.has_option("opt"));
299*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ(4, cmdline.arguments().size());
300*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("foo", cmdline.arguments()[0]);
301*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("-c", cmdline.arguments()[1]);
302*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("--opt", cmdline.arguments()[2]);
303*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("bar", cmdline.arguments()[3]);
304*11be35a1SLionel Sambuc }
305*11be35a1SLionel Sambuc 
306*11be35a1SLionel Sambuc 
307*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(some_options__all_known);
ATF_TEST_CASE_BODY(some_options__all_known)308*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(some_options__all_known)
309*11be35a1SLionel Sambuc {
310*11be35a1SLionel Sambuc     const int argc = 14;
311*11be35a1SLionel Sambuc     const char* const argv[] = {
312*11be35a1SLionel Sambuc         "progname",
313*11be35a1SLionel Sambuc         "-a",
314*11be35a1SLionel Sambuc         "-bvalue_b",
315*11be35a1SLionel Sambuc         "-c", "value_c",
316*11be35a1SLionel Sambuc         //"-d",  // Options with default optional values are unsupported.
317*11be35a1SLionel Sambuc         "-evalue_e",  // Has default; overriden.
318*11be35a1SLionel Sambuc         "--f_long",
319*11be35a1SLionel Sambuc         "--g_long=value_g",
320*11be35a1SLionel Sambuc         "--h_long", "value_h",
321*11be35a1SLionel Sambuc         //"--i_long",  // Options with default optional values are unsupported.
322*11be35a1SLionel Sambuc         "--j_long", "value_j",  // Has default; overriden as separate argument.
323*11be35a1SLionel Sambuc         "arg1", "arg2", NULL,
324*11be35a1SLionel Sambuc     };
325*11be35a1SLionel Sambuc     const bool_option a('a', "a_long", "");
326*11be35a1SLionel Sambuc     const string_option b('b', "b_long", "Description", "arg");
327*11be35a1SLionel Sambuc     const string_option c('c', "c_long", "ABCD", "foo");
328*11be35a1SLionel Sambuc     const string_option d('d', "d_long", "Description", "bar", "default_d");
329*11be35a1SLionel Sambuc     const string_option e('e', "e_long", "Description", "baz", "default_e");
330*11be35a1SLionel Sambuc     const bool_option f("f_long", "Description");
331*11be35a1SLionel Sambuc     const string_option g("g_long", "Description", "arg");
332*11be35a1SLionel Sambuc     const string_option h("h_long", "Description", "foo");
333*11be35a1SLionel Sambuc     const string_option i("i_long", "EFGH", "bar", "default_i");
334*11be35a1SLionel Sambuc     const string_option j("j_long", "Description", "baz", "default_j");
335*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
336*11be35a1SLionel Sambuc     options.push_back(&a);
337*11be35a1SLionel Sambuc     options.push_back(&b);
338*11be35a1SLionel Sambuc     options.push_back(&c);
339*11be35a1SLionel Sambuc     options.push_back(&d);
340*11be35a1SLionel Sambuc     options.push_back(&e);
341*11be35a1SLionel Sambuc     options.push_back(&f);
342*11be35a1SLionel Sambuc     options.push_back(&g);
343*11be35a1SLionel Sambuc     options.push_back(&h);
344*11be35a1SLionel Sambuc     options.push_back(&i);
345*11be35a1SLionel Sambuc     options.push_back(&j);
346*11be35a1SLionel Sambuc     const parsed_cmdline cmdline = parse(argc, argv, options);
347*11be35a1SLionel Sambuc 
348*11be35a1SLionel Sambuc     ATF_REQUIRE(cmdline.has_option("a_long"));
349*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("value_b", cmdline.get_option< string_option >("b_long"));
350*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("value_c", cmdline.get_option< string_option >("c_long"));
351*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("default_d", cmdline.get_option< string_option >("d_long"));
352*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("value_e", cmdline.get_option< string_option >("e_long"));
353*11be35a1SLionel Sambuc     ATF_REQUIRE(cmdline.has_option("f_long"));
354*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("value_g", cmdline.get_option< string_option >("g_long"));
355*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("value_h", cmdline.get_option< string_option >("h_long"));
356*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("default_i", cmdline.get_option< string_option >("i_long"));
357*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("value_j", cmdline.get_option< string_option >("j_long"));
358*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ(2, cmdline.arguments().size());
359*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("arg1", cmdline.arguments()[0]);
360*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("arg2", cmdline.arguments()[1]);
361*11be35a1SLionel Sambuc }
362*11be35a1SLionel Sambuc 
363*11be35a1SLionel Sambuc 
364*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(some_options__multi);
ATF_TEST_CASE_BODY(some_options__multi)365*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(some_options__multi)
366*11be35a1SLionel Sambuc {
367*11be35a1SLionel Sambuc     const int argc = 9;
368*11be35a1SLionel Sambuc     const char* const argv[] = {
369*11be35a1SLionel Sambuc         "progname",
370*11be35a1SLionel Sambuc         "-a1",
371*11be35a1SLionel Sambuc         "-bvalue1",
372*11be35a1SLionel Sambuc         "-a2",
373*11be35a1SLionel Sambuc         "--a_long=3",
374*11be35a1SLionel Sambuc         "-bvalue2",
375*11be35a1SLionel Sambuc         "--b_long=value3",
376*11be35a1SLionel Sambuc         "arg1", "arg2", NULL,
377*11be35a1SLionel Sambuc     };
378*11be35a1SLionel Sambuc     const int_option a('a', "a_long", "Description", "arg");
379*11be35a1SLionel Sambuc     const string_option b('b', "b_long", "Description", "arg");
380*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
381*11be35a1SLionel Sambuc     options.push_back(&a);
382*11be35a1SLionel Sambuc     options.push_back(&b);
383*11be35a1SLionel Sambuc     const parsed_cmdline cmdline = parse(argc, argv, options);
384*11be35a1SLionel Sambuc 
385*11be35a1SLionel Sambuc     {
386*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ(3, cmdline.get_option< int_option >("a_long"));
387*11be35a1SLionel Sambuc         const std::vector< int > multi =
388*11be35a1SLionel Sambuc             cmdline.get_multi_option< int_option >("a_long");
389*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ(3, multi.size());
390*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ(1, multi[0]);
391*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ(2, multi[1]);
392*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ(3, multi[2]);
393*11be35a1SLionel Sambuc     }
394*11be35a1SLionel Sambuc 
395*11be35a1SLionel Sambuc     {
396*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("value3", cmdline.get_option< string_option >("b_long"));
397*11be35a1SLionel Sambuc         const std::vector< std::string > multi =
398*11be35a1SLionel Sambuc             cmdline.get_multi_option< string_option >("b_long");
399*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ(3, multi.size());
400*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("value1", multi[0]);
401*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("value2", multi[1]);
402*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("value3", multi[2]);
403*11be35a1SLionel Sambuc     }
404*11be35a1SLionel Sambuc }
405*11be35a1SLionel Sambuc 
406*11be35a1SLionel Sambuc 
407*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(subcommands);
ATF_TEST_CASE_BODY(subcommands)408*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(subcommands)
409*11be35a1SLionel Sambuc {
410*11be35a1SLionel Sambuc     const int argc = 5;
411*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "--flag1", "subcommand",
412*11be35a1SLionel Sambuc                                 "--flag2", "arg", NULL};
413*11be35a1SLionel Sambuc     const bool_option flag1("flag1", "");
414*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
415*11be35a1SLionel Sambuc     options.push_back(&flag1);
416*11be35a1SLionel Sambuc     const parsed_cmdline cmdline = parse(argc, argv, options);
417*11be35a1SLionel Sambuc 
418*11be35a1SLionel Sambuc     ATF_REQUIRE( cmdline.has_option("flag1"));
419*11be35a1SLionel Sambuc     ATF_REQUIRE(!cmdline.has_option("flag2"));
420*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ(3, cmdline.arguments().size());
421*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("subcommand", cmdline.arguments()[0]);
422*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("--flag2", cmdline.arguments()[1]);
423*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("arg", cmdline.arguments()[2]);
424*11be35a1SLionel Sambuc 
425*11be35a1SLionel Sambuc     const bool_option flag2("flag2", "");
426*11be35a1SLionel Sambuc     std::vector< const base_option* > options2;
427*11be35a1SLionel Sambuc     options2.push_back(&flag2);
428*11be35a1SLionel Sambuc     const parsed_cmdline cmdline2 = parse(cmdline.arguments(), options2);
429*11be35a1SLionel Sambuc 
430*11be35a1SLionel Sambuc     ATF_REQUIRE(!cmdline2.has_option("flag1"));
431*11be35a1SLionel Sambuc     ATF_REQUIRE( cmdline2.has_option("flag2"));
432*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ(1, cmdline2.arguments().size());
433*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("arg", cmdline2.arguments()[0]);
434*11be35a1SLionel Sambuc }
435*11be35a1SLionel Sambuc 
436*11be35a1SLionel Sambuc 
437*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(missing_option_argument_error__short);
ATF_TEST_CASE_BODY(missing_option_argument_error__short)438*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(missing_option_argument_error__short)
439*11be35a1SLionel Sambuc {
440*11be35a1SLionel Sambuc     const int argc = 3;
441*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "-a3", "-b", NULL};
442*11be35a1SLionel Sambuc     const string_option flag1('a', "flag1", "Description", "arg");
443*11be35a1SLionel Sambuc     const string_option flag2('b', "flag2", "Description", "arg");
444*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
445*11be35a1SLionel Sambuc     options.push_back(&flag1);
446*11be35a1SLionel Sambuc     options.push_back(&flag2);
447*11be35a1SLionel Sambuc 
448*11be35a1SLionel Sambuc     try {
449*11be35a1SLionel Sambuc         parse(argc, argv, options);
450*11be35a1SLionel Sambuc         fail("missing_option_argument_error not raised");
451*11be35a1SLionel Sambuc     } catch (const cmdline::missing_option_argument_error& e) {
452*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("-b", e.option());
453*11be35a1SLionel Sambuc     } catch (const cmdline::unknown_option_error& e) {
454*11be35a1SLionel Sambuc         if (is_getopt_long_pluscolon_broken())
455*11be35a1SLionel Sambuc             expect_fail("Your getopt_long is broken");
456*11be35a1SLionel Sambuc         fail("Got unknown_option_error instead of "
457*11be35a1SLionel Sambuc              "missing_option_argument_error");
458*11be35a1SLionel Sambuc     }
459*11be35a1SLionel Sambuc }
460*11be35a1SLionel Sambuc 
461*11be35a1SLionel Sambuc 
462*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(missing_option_argument_error__shortblock);
ATF_TEST_CASE_BODY(missing_option_argument_error__shortblock)463*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(missing_option_argument_error__shortblock)
464*11be35a1SLionel Sambuc {
465*11be35a1SLionel Sambuc     const int argc = 3;
466*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "-ab3", "-ac", NULL};
467*11be35a1SLionel Sambuc     const bool_option flag1('a', "flag1", "Description");
468*11be35a1SLionel Sambuc     const string_option flag2('b', "flag2", "Description", "arg");
469*11be35a1SLionel Sambuc     const string_option flag3('c', "flag2", "Description", "arg");
470*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
471*11be35a1SLionel Sambuc     options.push_back(&flag1);
472*11be35a1SLionel Sambuc     options.push_back(&flag2);
473*11be35a1SLionel Sambuc     options.push_back(&flag3);
474*11be35a1SLionel Sambuc 
475*11be35a1SLionel Sambuc     try {
476*11be35a1SLionel Sambuc         parse(argc, argv, options);
477*11be35a1SLionel Sambuc         fail("missing_option_argument_error not raised");
478*11be35a1SLionel Sambuc     } catch (const cmdline::missing_option_argument_error& e) {
479*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("-c", e.option());
480*11be35a1SLionel Sambuc     } catch (const cmdline::unknown_option_error& e) {
481*11be35a1SLionel Sambuc         if (is_getopt_long_pluscolon_broken())
482*11be35a1SLionel Sambuc             expect_fail("Your getopt_long is broken");
483*11be35a1SLionel Sambuc         fail("Got unknown_option_error instead of "
484*11be35a1SLionel Sambuc              "missing_option_argument_error");
485*11be35a1SLionel Sambuc     }
486*11be35a1SLionel Sambuc }
487*11be35a1SLionel Sambuc 
488*11be35a1SLionel Sambuc 
489*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(missing_option_argument_error__long);
ATF_TEST_CASE_BODY(missing_option_argument_error__long)490*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(missing_option_argument_error__long)
491*11be35a1SLionel Sambuc {
492*11be35a1SLionel Sambuc     const int argc = 3;
493*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "--flag1=a", "--flag2", NULL};
494*11be35a1SLionel Sambuc     const string_option flag1("flag1", "Description", "arg");
495*11be35a1SLionel Sambuc     const string_option flag2("flag2", "Description", "arg");
496*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
497*11be35a1SLionel Sambuc     options.push_back(&flag1);
498*11be35a1SLionel Sambuc     options.push_back(&flag2);
499*11be35a1SLionel Sambuc 
500*11be35a1SLionel Sambuc     try {
501*11be35a1SLionel Sambuc         parse(argc, argv, options);
502*11be35a1SLionel Sambuc         fail("missing_option_argument_error not raised");
503*11be35a1SLionel Sambuc     } catch (const cmdline::missing_option_argument_error& e) {
504*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("--flag2", e.option());
505*11be35a1SLionel Sambuc     } catch (const cmdline::unknown_option_error& e) {
506*11be35a1SLionel Sambuc         if (is_getopt_long_pluscolon_broken())
507*11be35a1SLionel Sambuc             expect_fail("Your getopt_long is broken");
508*11be35a1SLionel Sambuc         fail("Got unknown_option_error instead of "
509*11be35a1SLionel Sambuc              "missing_option_argument_error");
510*11be35a1SLionel Sambuc     }
511*11be35a1SLionel Sambuc }
512*11be35a1SLionel Sambuc 
513*11be35a1SLionel Sambuc 
514*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(unknown_option_error__short);
ATF_TEST_CASE_BODY(unknown_option_error__short)515*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(unknown_option_error__short)
516*11be35a1SLionel Sambuc {
517*11be35a1SLionel Sambuc     const int argc = 3;
518*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "-a", "-b", NULL};
519*11be35a1SLionel Sambuc     const bool_option flag1('a', "flag1", "Description");
520*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
521*11be35a1SLionel Sambuc     options.push_back(&flag1);
522*11be35a1SLionel Sambuc 
523*11be35a1SLionel Sambuc     try {
524*11be35a1SLionel Sambuc         parse(argc, argv, options);
525*11be35a1SLionel Sambuc         fail("unknown_option_error not raised");
526*11be35a1SLionel Sambuc     } catch (const cmdline::unknown_option_error& e) {
527*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("-b", e.option());
528*11be35a1SLionel Sambuc     }
529*11be35a1SLionel Sambuc }
530*11be35a1SLionel Sambuc 
531*11be35a1SLionel Sambuc 
532*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(unknown_option_error__shortblock);
ATF_TEST_CASE_BODY(unknown_option_error__shortblock)533*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(unknown_option_error__shortblock)
534*11be35a1SLionel Sambuc {
535*11be35a1SLionel Sambuc     const int argc = 3;
536*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "-a", "-bdc", NULL};
537*11be35a1SLionel Sambuc     const bool_option flag1('a', "flag1", "Description");
538*11be35a1SLionel Sambuc     const bool_option flag2('b', "flag2", "Description");
539*11be35a1SLionel Sambuc     const bool_option flag3('c', "flag3", "Description");
540*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
541*11be35a1SLionel Sambuc     options.push_back(&flag1);
542*11be35a1SLionel Sambuc     options.push_back(&flag2);
543*11be35a1SLionel Sambuc     options.push_back(&flag3);
544*11be35a1SLionel Sambuc 
545*11be35a1SLionel Sambuc     try {
546*11be35a1SLionel Sambuc         parse(argc, argv, options);
547*11be35a1SLionel Sambuc         fail("unknown_option_error not raised");
548*11be35a1SLionel Sambuc     } catch (const cmdline::unknown_option_error& e) {
549*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("-d", e.option());
550*11be35a1SLionel Sambuc     }
551*11be35a1SLionel Sambuc }
552*11be35a1SLionel Sambuc 
553*11be35a1SLionel Sambuc 
554*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(unknown_option_error__long);
ATF_TEST_CASE_BODY(unknown_option_error__long)555*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(unknown_option_error__long)
556*11be35a1SLionel Sambuc {
557*11be35a1SLionel Sambuc     const int argc = 3;
558*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "--flag1=a", "--flag2", NULL};
559*11be35a1SLionel Sambuc     const string_option flag1("flag1", "Description", "arg");
560*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
561*11be35a1SLionel Sambuc     options.push_back(&flag1);
562*11be35a1SLionel Sambuc 
563*11be35a1SLionel Sambuc     try {
564*11be35a1SLionel Sambuc         parse(argc, argv, options);
565*11be35a1SLionel Sambuc         fail("unknown_option_error not raised");
566*11be35a1SLionel Sambuc     } catch (const cmdline::unknown_option_error& e) {
567*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("--flag2", e.option());
568*11be35a1SLionel Sambuc     }
569*11be35a1SLionel Sambuc }
570*11be35a1SLionel Sambuc 
571*11be35a1SLionel Sambuc 
572*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(unknown_plus_option_error);
ATF_TEST_CASE_BODY(unknown_plus_option_error)573*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(unknown_plus_option_error)
574*11be35a1SLionel Sambuc {
575*11be35a1SLionel Sambuc     const int argc = 2;
576*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "-+", NULL};
577*11be35a1SLionel Sambuc     const cmdline::options_vector options;
578*11be35a1SLionel Sambuc 
579*11be35a1SLionel Sambuc     try {
580*11be35a1SLionel Sambuc         parse(argc, argv, options);
581*11be35a1SLionel Sambuc         fail("unknown_option_error not raised");
582*11be35a1SLionel Sambuc     } catch (const cmdline::unknown_option_error& e) {
583*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("-+", e.option());
584*11be35a1SLionel Sambuc     } catch (const cmdline::missing_option_argument_error& e) {
585*11be35a1SLionel Sambuc         fail("Looks like getopt_long thinks a + option is defined and it "
586*11be35a1SLionel Sambuc              "even requires an argument");
587*11be35a1SLionel Sambuc     }
588*11be35a1SLionel Sambuc }
589*11be35a1SLionel Sambuc 
590*11be35a1SLionel Sambuc 
591*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(option_types);
ATF_TEST_CASE_BODY(option_types)592*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(option_types)
593*11be35a1SLionel Sambuc {
594*11be35a1SLionel Sambuc     const int argc = 3;
595*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "--flag1=a", "--flag2=one", NULL};
596*11be35a1SLionel Sambuc     const string_option flag1("flag1", "The flag1", "arg");
597*11be35a1SLionel Sambuc     const mock_option flag2("flag2");
598*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
599*11be35a1SLionel Sambuc     options.push_back(&flag1);
600*11be35a1SLionel Sambuc     options.push_back(&flag2);
601*11be35a1SLionel Sambuc 
602*11be35a1SLionel Sambuc     const parsed_cmdline cmdline = parse(argc, argv, options);
603*11be35a1SLionel Sambuc 
604*11be35a1SLionel Sambuc     ATF_REQUIRE(cmdline.has_option("flag1"));
605*11be35a1SLionel Sambuc     ATF_REQUIRE(cmdline.has_option("flag2"));
606*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ("a", cmdline.get_option< string_option >("flag1"));
607*11be35a1SLionel Sambuc     ATF_REQUIRE_EQ(1, cmdline.get_option< mock_option >("flag2"));
608*11be35a1SLionel Sambuc }
609*11be35a1SLionel Sambuc 
610*11be35a1SLionel Sambuc 
611*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(option_validation_error);
ATF_TEST_CASE_BODY(option_validation_error)612*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(option_validation_error)
613*11be35a1SLionel Sambuc {
614*11be35a1SLionel Sambuc     const int argc = 3;
615*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "--flag1=zero", "--flag2=foo",
616*11be35a1SLionel Sambuc                                 NULL};
617*11be35a1SLionel Sambuc     const mock_option flag1("flag1");
618*11be35a1SLionel Sambuc     const mock_option flag2("flag2");
619*11be35a1SLionel Sambuc     std::vector< const base_option* > options;
620*11be35a1SLionel Sambuc     options.push_back(&flag1);
621*11be35a1SLionel Sambuc     options.push_back(&flag2);
622*11be35a1SLionel Sambuc 
623*11be35a1SLionel Sambuc     try {
624*11be35a1SLionel Sambuc         parse(argc, argv, options);
625*11be35a1SLionel Sambuc         fail("option_argument_value_error not raised");
626*11be35a1SLionel Sambuc     } catch (const cmdline::option_argument_value_error& e) {
627*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("--flag2", e.option());
628*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("foo", e.argument());
629*11be35a1SLionel Sambuc     }
630*11be35a1SLionel Sambuc }
631*11be35a1SLionel Sambuc 
632*11be35a1SLionel Sambuc 
633*11be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(silent_errors);
ATF_TEST_CASE_BODY(silent_errors)634*11be35a1SLionel Sambuc ATF_TEST_CASE_BODY(silent_errors)
635*11be35a1SLionel Sambuc {
636*11be35a1SLionel Sambuc     const int argc = 2;
637*11be35a1SLionel Sambuc     const char* const argv[] = {"progname", "-h", NULL};
638*11be35a1SLionel Sambuc     cmdline::options_vector options;
639*11be35a1SLionel Sambuc 
640*11be35a1SLionel Sambuc     try {
641*11be35a1SLionel Sambuc         std::pair< int, int > oldfds = mock_stdfds("output.txt");
642*11be35a1SLionel Sambuc         try {
643*11be35a1SLionel Sambuc             parse(argc, argv, options);
644*11be35a1SLionel Sambuc         } catch (...) {
645*11be35a1SLionel Sambuc             restore_stdfds(oldfds);
646*11be35a1SLionel Sambuc             throw;
647*11be35a1SLionel Sambuc         }
648*11be35a1SLionel Sambuc         restore_stdfds(oldfds);
649*11be35a1SLionel Sambuc         fail("unknown_option_error not raised");
650*11be35a1SLionel Sambuc     } catch (const cmdline::unknown_option_error& e) {
651*11be35a1SLionel Sambuc         ATF_REQUIRE_EQ("-h", e.option());
652*11be35a1SLionel Sambuc     }
653*11be35a1SLionel Sambuc 
654*11be35a1SLionel Sambuc     std::ifstream input("output.txt");
655*11be35a1SLionel Sambuc     ATF_REQUIRE(input);
656*11be35a1SLionel Sambuc 
657*11be35a1SLionel Sambuc     bool has_output = false;
658*11be35a1SLionel Sambuc     std::string line;
659*11be35a1SLionel Sambuc     while (std::getline(input, line).good()) {
660*11be35a1SLionel Sambuc         std::cout << line << '\n';
661*11be35a1SLionel Sambuc         has_output = true;
662*11be35a1SLionel Sambuc     }
663*11be35a1SLionel Sambuc 
664*11be35a1SLionel Sambuc     if (has_output)
665*11be35a1SLionel Sambuc         fail("getopt_long printed messages on stdout/stderr by itself");
666*11be35a1SLionel Sambuc }
667*11be35a1SLionel Sambuc 
668*11be35a1SLionel Sambuc 
ATF_INIT_TEST_CASES(tcs)669*11be35a1SLionel Sambuc ATF_INIT_TEST_CASES(tcs)
670*11be35a1SLionel Sambuc {
671*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, progname__no_options);
672*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, progname__some_options);
673*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, some_args__no_options);
674*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, some_args__some_options);
675*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, some_options__all_known);
676*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, some_options__multi);
677*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, subcommands);
678*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, missing_option_argument_error__short);
679*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, missing_option_argument_error__shortblock);
680*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, missing_option_argument_error__long);
681*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, unknown_option_error__short);
682*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, unknown_option_error__shortblock);
683*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, unknown_option_error__long);
684*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, unknown_plus_option_error);
685*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, option_types);
686*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, option_validation_error);
687*11be35a1SLionel Sambuc     ATF_ADD_TEST_CASE(tcs, silent_errors);
688*11be35a1SLionel Sambuc }
689