Skip to content

Commit d44f6a1

Browse files
committed
[TEST] Add tests
1 parent af92d15 commit d44f6a1

File tree

4 files changed

+259
-8
lines changed

4 files changed

+259
-8
lines changed

test/unit/parser/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ sharg_test (enumeration_names_test.cpp)
66
sharg_test (format_parse_test.cpp)
77
sharg_test (format_parse_validators_test.cpp)
88
sharg_test (parser_design_error_test.cpp)
9+
sharg_test (subcommand_test.cpp)

test/unit/parser/format_parse_test.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -681,17 +681,20 @@ TEST_F(format_parse_test, subcommand_parser_success)
681681

682682
TEST_F(format_parse_test, subcommand_parser_error)
683683
{
684+
constexpr std::string_view expected_message = "You specified an unknown subcommand! Available subcommands are: "
685+
"[sub1]. Use -h/--help for more information.";
686+
684687
// incorrect sub command regardless of following arguments, https://github.com/seqan/seqan3/issues/2172
685688
auto parser = get_subcommand_parser({"subiddysub", "-f"}, {"sub1"});
686-
EXPECT_THROW(parser.parse(), sharg::parser_error);
689+
EXPECT_THROW_MSG(parser.parse(), sharg::user_input_error, expected_message);
687690

688691
// incorrect sub command with no other arguments
689692
parser = get_subcommand_parser({"subiddysub"}, {"sub1"});
690-
EXPECT_THROW(parser.parse(), sharg::parser_error);
693+
EXPECT_THROW_MSG(parser.parse(), sharg::user_input_error, expected_message);
691694

692695
// incorrect sub command with trailing special option, https://github.com/seqan/sharg-parser/issues/171
693696
parser = get_subcommand_parser({"subiddysub", "-h"}, {"sub1"});
694-
EXPECT_THROW(parser.parse(), sharg::parser_error);
697+
EXPECT_THROW_MSG(parser.parse(), sharg::user_input_error, expected_message);
695698
}
696699

697700
TEST_F(format_parse_test, issue1544)

test/unit/parser/parser_design_error_test.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ TEST_F(design_error_test, subcommand_parser_error)
267267
parser = get_subcommand_parser({"-f", "foo"}, {"foo"});
268268

269269
EXPECT_THROW(parser.add_positional_option(flag_value, sharg::config{}), sharg::design_error);
270-
EXPECT_THROW(parser.add_option(flag_value, sharg::config{.short_id = 'o'}), sharg::design_error);
270+
EXPECT_NO_THROW(parser.add_option(flag_value, sharg::config{.short_id = 'o'}));
271271
EXPECT_NO_THROW(parser.add_flag(flag_value, sharg::config{.short_id = 'f'}));
272272
EXPECT_THROW(parser.get_sub_parser(), sharg::design_error);
273273
EXPECT_EQ(flag_value, false);
@@ -277,14 +277,14 @@ TEST_F(design_error_test, subcommand_parser_error)
277277

278278
flag_value = false;
279279

280-
// no options are allowed
280+
// options are allowed
281281
parser = get_subcommand_parser({"-o", "true"}, {"foo"});
282282

283283
EXPECT_THROW(parser.add_positional_option(flag_value, sharg::config{}), sharg::design_error);
284-
EXPECT_THROW(parser.add_option(flag_value, sharg::config{.short_id = 'o'}), sharg::design_error);
285-
EXPECT_EQ(flag_value, false);
286-
EXPECT_THROW(parser.parse(), sharg::too_few_arguments);
284+
EXPECT_NO_THROW(parser.add_option(flag_value, sharg::config{.short_id = 'o'}));
287285
EXPECT_EQ(flag_value, false);
286+
EXPECT_NO_THROW(parser.parse());
287+
EXPECT_EQ(flag_value, true);
288288
}
289289

290290
TEST_F(design_error_test, not_allowed_after_parse)
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
// SPDX-FileCopyrightText: 2006-2024, Knut Reinert & Freie Universität Berlin
2+
// SPDX-FileCopyrightText: 2016-2024, Knut Reinert & MPI für molekulare Genetik
3+
// SPDX-License-Identifier: BSD-3-Clause
4+
5+
#include <gtest/gtest.h>
6+
7+
#include <ranges>
8+
9+
#include <sharg/parser.hpp>
10+
#include <sharg/test/expect_throw_msg.hpp>
11+
#include <sharg/test/test_fixture.hpp>
12+
13+
class subcommand_test : public sharg::test::test_fixture
14+
{
15+
protected:
16+
static constexpr std::string_view expected_top_short_help = "test_parser\n===========n"
17+
" Try -h or --help for more information.\n";
18+
19+
static inline std::string expected_top_full_help =
20+
"test_parser\n"
21+
"===========\n"
22+
"\n"
23+
"SUBCOMMANDS\n"
24+
" This program must be invoked with one of the following subcommands:\n"
25+
" - build\n"
26+
" See the respective help page for further details (e.g. by calling\n"
27+
" test_parser build -h).\n"
28+
"\n"
29+
" The following options belong to the top-level parser and need to be\n"
30+
" specified before the subcommand key word. Every argument after the\n"
31+
" subcommand key word is passed on to the corresponding sub-parser.\n"
32+
"\n"
33+
"OPTIONS\n"
34+
" -o (std::string)\n"
35+
" Default: \"\"\n"
36+
"\n"
37+
+ basic_options_str + '\n' + version_str();
38+
39+
static constexpr std::string_view expected_sub_short_help = "test_parser-build\n=================\n"
40+
" Try -h or --help for more information.\n";
41+
42+
static inline std::string expected_sub_full_help = "test_parser-build\n"
43+
"=================\n"
44+
"\n"
45+
"OPTIONS\n"
46+
" -o (std::string)\n"
47+
" Default: \"\"\n"
48+
"\n"
49+
+ basic_options_str + '\n' + version_str("-build");
50+
51+
static inline std::string value{};
52+
53+
static inline void clear_and_add_option(sharg::parser & parser)
54+
{
55+
value.clear();
56+
parser.add_option(value, sharg::config{.short_id = 'o'});
57+
}
58+
};
59+
60+
TEST_F(subcommand_test, simple_option)
61+
{
62+
auto parser = get_subcommand_parser({"build", "-o", "foo"}, {"build"});
63+
EXPECT_NO_THROW(parser.parse());
64+
65+
ASSERT_NO_THROW(parser.get_sub_parser());
66+
auto & sub_parser = parser.get_sub_parser();
67+
clear_and_add_option(sub_parser);
68+
69+
EXPECT_NO_THROW(sub_parser.parse());
70+
EXPECT_EQ(value, "foo");
71+
}
72+
73+
TEST_F(subcommand_test, subcommand_is_option_value)
74+
{
75+
auto parser = get_subcommand_parser({"-o", "build", "build", "-o", "build"}, {"build"});
76+
clear_and_add_option(parser);
77+
EXPECT_NO_THROW(parser.parse());
78+
EXPECT_EQ(value, "build");
79+
80+
ASSERT_NO_THROW(parser.get_sub_parser());
81+
auto & sub_parser = parser.get_sub_parser();
82+
clear_and_add_option(sub_parser);
83+
84+
EXPECT_NO_THROW(sub_parser.parse());
85+
EXPECT_EQ(value, "build");
86+
}
87+
88+
TEST_F(subcommand_test, option_value_is_option)
89+
{
90+
auto parser = get_subcommand_parser({"-o", "-o", "build", "-o", "-o"}, {"build"});
91+
clear_and_add_option(parser);
92+
EXPECT_NO_THROW(parser.parse());
93+
EXPECT_EQ(value, "-o");
94+
95+
ASSERT_NO_THROW(parser.get_sub_parser());
96+
auto & sub_parser = parser.get_sub_parser();
97+
clear_and_add_option(sub_parser);
98+
99+
EXPECT_NO_THROW(sub_parser.parse());
100+
EXPECT_EQ(value, "-o");
101+
}
102+
103+
TEST_F(subcommand_test, wrong_subcommand)
104+
{
105+
constexpr std::string_view expected_message = "You specified an unknown subcommand! Available subcommands are: "
106+
"[build]. Use -h/--help for more information.";
107+
108+
auto parser = get_subcommand_parser({"-o", "build", "buidl", "-o", "build"}, {"build"});
109+
clear_and_add_option(parser);
110+
EXPECT_THROW_MSG(parser.parse(), sharg::user_input_error, expected_message);
111+
EXPECT_EQ(value, "");
112+
}
113+
114+
TEST_F(subcommand_test, subcommand_is_option_value_equals_syntax)
115+
{
116+
auto parser = get_subcommand_parser({"-o=build", "build", "-o=build"}, {"build"});
117+
clear_and_add_option(parser);
118+
EXPECT_NO_THROW(parser.parse());
119+
EXPECT_EQ(value, "build");
120+
121+
ASSERT_NO_THROW(parser.get_sub_parser());
122+
auto & sub_parser = parser.get_sub_parser();
123+
clear_and_add_option(sub_parser);
124+
125+
EXPECT_NO_THROW(sub_parser.parse());
126+
EXPECT_EQ(value, "build");
127+
}
128+
129+
TEST_F(subcommand_test, subcommand_is_flag)
130+
{
131+
std::array<bool, 5> flag_values{false, false, false, false, false};
132+
133+
auto parser = get_subcommand_parser({"-build", "build", "-o", "build"}, {"build"});
134+
parser.add_flag(flag_values[0], sharg::config{.short_id = 'b'});
135+
parser.add_flag(flag_values[1], sharg::config{.short_id = 'u'});
136+
parser.add_flag(flag_values[2], sharg::config{.short_id = 'i'});
137+
parser.add_flag(flag_values[3], sharg::config{.short_id = 'l'});
138+
parser.add_flag(flag_values[4], sharg::config{.short_id = 'd'});
139+
EXPECT_NO_THROW(parser.parse());
140+
EXPECT_TRUE(std::ranges::all_of(flag_values, std::identity{})); // All true
141+
142+
ASSERT_NO_THROW(parser.get_sub_parser());
143+
auto & sub_parser = parser.get_sub_parser();
144+
clear_and_add_option(sub_parser);
145+
146+
EXPECT_NO_THROW(sub_parser.parse());
147+
EXPECT_EQ(value, "build");
148+
}
149+
150+
TEST_F(subcommand_test, no_help)
151+
{
152+
auto parser = get_subcommand_parser({"-o", "build"}, {"build"});
153+
clear_and_add_option(parser);
154+
EXPECT_NO_THROW(parser.parse());
155+
EXPECT_EQ(value, "build");
156+
}
157+
158+
TEST_F(subcommand_test, top_full_help)
159+
{
160+
auto parser = get_subcommand_parser({"-o", "build", "--help"}, {"build"});
161+
clear_and_add_option(parser);
162+
EXPECT_EQ(get_parse_cout_on_exit(parser), expected_top_full_help);
163+
EXPECT_EQ(value, "");
164+
}
165+
166+
TEST_F(subcommand_test, sub_short_help)
167+
{
168+
auto parser = get_subcommand_parser({"-o", "build", "build"}, {"build"});
169+
clear_and_add_option(parser);
170+
EXPECT_NO_THROW(parser.parse());
171+
EXPECT_EQ(value, "build");
172+
173+
ASSERT_NO_THROW(parser.get_sub_parser());
174+
auto & sub_parser = parser.get_sub_parser();
175+
clear_and_add_option(sub_parser);
176+
177+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_short_help);
178+
EXPECT_EQ(value, "");
179+
}
180+
181+
TEST_F(subcommand_test, sub_full_help)
182+
{
183+
auto parser = get_subcommand_parser({"-o", "build", "build", "--help"}, {"build"});
184+
clear_and_add_option(parser);
185+
EXPECT_NO_THROW(parser.parse());
186+
EXPECT_EQ(value, "build");
187+
188+
ASSERT_NO_THROW(parser.get_sub_parser());
189+
auto & sub_parser = parser.get_sub_parser();
190+
clear_and_add_option(sub_parser);
191+
192+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_full_help);
193+
EXPECT_EQ(value, "");
194+
}
195+
196+
TEST_F(subcommand_test, sub_short_help_no_options)
197+
{
198+
auto parser = get_subcommand_parser({"build"}, {"build"});
199+
clear_and_add_option(parser);
200+
EXPECT_NO_THROW(parser.parse());
201+
EXPECT_EQ(value, "");
202+
203+
ASSERT_NO_THROW(parser.get_sub_parser());
204+
auto & sub_parser = parser.get_sub_parser();
205+
clear_and_add_option(sub_parser);
206+
207+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_short_help);
208+
EXPECT_EQ(value, "");
209+
}
210+
211+
TEST_F(subcommand_test, sub_full_help_no_options)
212+
{
213+
auto parser = get_subcommand_parser({"build", "--help"}, {"build"});
214+
clear_and_add_option(parser);
215+
EXPECT_NO_THROW(parser.parse());
216+
EXPECT_EQ(value, "");
217+
218+
ASSERT_NO_THROW(parser.get_sub_parser());
219+
auto & sub_parser = parser.get_sub_parser();
220+
clear_and_add_option(sub_parser);
221+
222+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_full_help);
223+
EXPECT_EQ(value, "");
224+
}
225+
226+
TEST_F(subcommand_test, sub_full_help_all_options)
227+
{
228+
auto parser = get_subcommand_parser({"-o", "build", "build", "-o", "build", "--help"}, {"build"});
229+
clear_and_add_option(parser);
230+
EXPECT_NO_THROW(parser.parse());
231+
EXPECT_EQ(value, "build");
232+
233+
ASSERT_NO_THROW(parser.get_sub_parser());
234+
auto & sub_parser = parser.get_sub_parser();
235+
clear_and_add_option(sub_parser);
236+
237+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_full_help);
238+
EXPECT_EQ(value, "");
239+
}
240+
241+
TEST_F(subcommand_test, option_value_is_special_command)
242+
{
243+
auto parser = get_subcommand_parser({"-o", "--help"}, {"build"});
244+
clear_and_add_option(parser);
245+
EXPECT_NO_THROW(parser.parse());
246+
EXPECT_EQ(value, "--help");
247+
}

0 commit comments

Comments
 (0)