Skip to content

Commit a236f78

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

File tree

4 files changed

+245
-8
lines changed

4 files changed

+245
-8
lines changed

test/unit/parser/CMakeLists.txt

+1
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

+6-3
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

+5-5
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)

test/unit/parser/subcommand_test.cpp

+233
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
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+
}
112+
113+
TEST_F(subcommand_test, subcommand_is_option_value_equals_syntax)
114+
{
115+
auto parser = get_subcommand_parser({"-o=build", "build", "-o=build"}, {"build"});
116+
clear_and_add_option(parser);
117+
EXPECT_NO_THROW(parser.parse());
118+
EXPECT_EQ(value, "build");
119+
120+
ASSERT_NO_THROW(parser.get_sub_parser());
121+
auto & sub_parser = parser.get_sub_parser();
122+
clear_and_add_option(sub_parser);
123+
124+
EXPECT_NO_THROW(sub_parser.parse());
125+
EXPECT_EQ(value, "build");
126+
}
127+
128+
TEST_F(subcommand_test, subcommand_is_flag)
129+
{
130+
std::array<bool, 5> flag_values{false, false, false, false, false};
131+
132+
auto parser = get_subcommand_parser({"-build", "build", "-o", "build"}, {"build"});
133+
parser.add_flag(flag_values[0], sharg::config{.short_id = 'b'});
134+
parser.add_flag(flag_values[1], sharg::config{.short_id = 'u'});
135+
parser.add_flag(flag_values[2], sharg::config{.short_id = 'i'});
136+
parser.add_flag(flag_values[3], sharg::config{.short_id = 'l'});
137+
parser.add_flag(flag_values[4], sharg::config{.short_id = 'd'});
138+
EXPECT_NO_THROW(parser.parse());
139+
EXPECT_TRUE(std::ranges::all_of(flag_values, std::identity{})); // All true
140+
141+
ASSERT_NO_THROW(parser.get_sub_parser());
142+
auto & sub_parser = parser.get_sub_parser();
143+
clear_and_add_option(sub_parser);
144+
145+
EXPECT_NO_THROW(sub_parser.parse());
146+
EXPECT_EQ(value, "build");
147+
}
148+
149+
TEST_F(subcommand_test, no_help)
150+
{
151+
auto parser = get_subcommand_parser({"-o", "build"}, {"build"});
152+
clear_and_add_option(parser);
153+
EXPECT_NO_THROW(parser.parse());
154+
}
155+
156+
TEST_F(subcommand_test, top_full_help)
157+
{
158+
auto parser = get_subcommand_parser({"-o", "build", "--help"}, {"build"});
159+
clear_and_add_option(parser);
160+
EXPECT_EQ(get_parse_cout_on_exit(parser), expected_top_full_help);
161+
}
162+
163+
TEST_F(subcommand_test, sub_short_help)
164+
{
165+
auto parser = get_subcommand_parser({"-o", "build", "build"}, {"build"});
166+
clear_and_add_option(parser);
167+
EXPECT_NO_THROW(parser.parse());
168+
169+
ASSERT_NO_THROW(parser.get_sub_parser());
170+
auto & sub_parser = parser.get_sub_parser();
171+
clear_and_add_option(sub_parser);
172+
173+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_short_help);
174+
}
175+
176+
TEST_F(subcommand_test, sub_full_help)
177+
{
178+
auto parser = get_subcommand_parser({"-o", "build", "build", "--help"}, {"build"});
179+
clear_and_add_option(parser);
180+
EXPECT_NO_THROW(parser.parse());
181+
182+
ASSERT_NO_THROW(parser.get_sub_parser());
183+
auto & sub_parser = parser.get_sub_parser();
184+
clear_and_add_option(sub_parser);
185+
186+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_full_help);
187+
}
188+
189+
TEST_F(subcommand_test, sub_short_help_no_options)
190+
{
191+
auto parser = get_subcommand_parser({"build"}, {"build"});
192+
clear_and_add_option(parser);
193+
EXPECT_NO_THROW(parser.parse());
194+
195+
ASSERT_NO_THROW(parser.get_sub_parser());
196+
auto & sub_parser = parser.get_sub_parser();
197+
clear_and_add_option(sub_parser);
198+
199+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_short_help);
200+
}
201+
202+
TEST_F(subcommand_test, sub_full_help_no_options)
203+
{
204+
auto parser = get_subcommand_parser({"build", "--help"}, {"build"});
205+
clear_and_add_option(parser);
206+
EXPECT_NO_THROW(parser.parse());
207+
208+
ASSERT_NO_THROW(parser.get_sub_parser());
209+
auto & sub_parser = parser.get_sub_parser();
210+
clear_and_add_option(sub_parser);
211+
212+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_full_help);
213+
}
214+
215+
TEST_F(subcommand_test, sub_full_help_all_options)
216+
{
217+
auto parser = get_subcommand_parser({"-o", "build", "build", "-o", "build", "--help"}, {"build"});
218+
clear_and_add_option(parser);
219+
EXPECT_NO_THROW(parser.parse());
220+
221+
ASSERT_NO_THROW(parser.get_sub_parser());
222+
auto & sub_parser = parser.get_sub_parser();
223+
clear_and_add_option(sub_parser);
224+
225+
EXPECT_EQ(get_parse_cout_on_exit(sub_parser), expected_sub_full_help);
226+
}
227+
228+
TEST_F(subcommand_test, option_value_is_special_command)
229+
{
230+
auto parser = get_subcommand_parser({"-o", "--help"}, {"build"});
231+
clear_and_add_option(parser);
232+
EXPECT_NO_THROW(parser.parse());
233+
}

0 commit comments

Comments
 (0)