Toolbox
snapshot
The Reactive C++ Toolbox
Loading...
Searching...
No Matches
toolbox
util
Argv.ut.cpp
Go to the documentation of this file.
1
// The Reactive C++ Toolbox.
2
// Copyright (C) 2013-2019 Swirly Cloud Limited
3
// Copyright (C) 2021 Reactive Markets Limited
4
//
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the License is distributed on an "AS IS" BASIS,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the License for the specific language governing permissions and
15
// limitations under the License.
16
17
#include "
Argv.hpp
"
18
19
#include <boost/test/unit_test.hpp>
20
21
#include <iostream>
22
23
using namespace
std
;
24
using namespace
toolbox
;
25
26
namespace
{
27
28
struct
Opts {
29
vector<string_view>
args, fruit, veg;
30
bool
blend{
false
};
31
};
32
33
void
get_opts
(
int
argc
,
const
char
*
const
argv
[], Opts&
opts
)
34
{
35
ArgvLexer
lex
{
argc
,
argv
};
36
while
(!
lex
.empty()) {
37
const
auto
opt =
lex
.
opt
();
38
if
(opt.empty()) {
39
opts
.args.push_back(
lex
.pop_value());
40
}
else
if
(opt ==
"b"
|| opt ==
"blend"
) {
41
opts
.blend =
true
;
42
lex
.pop_switch();
43
}
else
if
(opt ==
"f"
|| opt ==
"fruit"
) {
44
opts
.fruit.push_back(
lex
.pop_value());
45
}
else
if
(opt ==
"v"
|| opt ==
"veg"
) {
46
opts
.veg.push_back(
lex
.pop_value());
47
}
else
{
48
throw
runtime_error{
"unknown option: "
+
string
{opt}};
49
}
50
}
51
}
52
53
template
<
size_t
N>
54
using
Argv
=
array<const char*, N>
;
55
56
}
// namespace
57
58
BOOST_AUTO_TEST_SUITE
(
ArgvSuite
)
59
60
BOOST_AUTO_TEST_CASE
(
ArgvEmptyCase
)
61
{
62
Opts
opts
;
63
Argv<0>
argv
{};
64
get_opts
(
argv
.size(),
argv
.data(),
opts
);
65
66
BOOST_CHECK
(
opts
.args.empty());
67
BOOST_CHECK
(
opts
.fruit.empty());
68
BOOST_CHECK
(
opts
.veg.empty());
69
BOOST_CHECK
(!
opts
.blend);
70
}
71
72
BOOST_AUTO_TEST_CASE
(
ArgvPositionalCase
)
73
{
74
Opts
opts
;
75
Argv<5>
argv
{
"foo"
,
"-"
,
"bar"
,
"--"
,
"baz"
};
76
get_opts
(
argv
.size(),
argv
.data(),
opts
);
77
78
BOOST_CHECK_EQUAL
(
opts
.args.size(), 5);
79
BOOST_CHECK_EQUAL
(
opts
.args.at(0),
"foo"
sv
);
80
BOOST_CHECK_EQUAL
(
opts
.args.at(1),
"-"
sv
);
81
BOOST_CHECK_EQUAL
(
opts
.args.at(2),
"bar"
sv
);
82
BOOST_CHECK_EQUAL
(
opts
.args.at(3),
"--"
sv
);
83
BOOST_CHECK_EQUAL
(
opts
.args.at(4),
"baz"
sv
);
84
BOOST_CHECK
(
opts
.fruit.empty());
85
BOOST_CHECK
(
opts
.veg.empty());
86
BOOST_CHECK
(!
opts
.blend);
87
}
88
89
BOOST_AUTO_TEST_CASE
(
ArgvShortOptCase
)
90
{
91
{
92
Opts
opts
;
93
Argv<2>
argv
{
"-fapple"
,
"-vcarrot"
};
94
get_opts
(
argv
.size(),
argv
.data(),
opts
);
95
96
BOOST_CHECK
(
opts
.args.empty());
97
BOOST_CHECK_EQUAL
(
opts
.fruit.size(), 1);
98
BOOST_CHECK_EQUAL
(
opts
.fruit.at(0),
"apple"
sv
);
99
BOOST_CHECK_EQUAL
(
opts
.veg.size(), 1);
100
BOOST_CHECK_EQUAL
(
opts
.veg.at(0),
"carrot"
sv
);
101
BOOST_CHECK
(!
opts
.blend);
102
}
103
{
104
Opts
opts
;
105
Argv<4>
argv
{
"-v"
,
"carrot"
,
"-f"
,
"apple"
};
106
get_opts
(
argv
.size(),
argv
.data(),
opts
);
107
108
BOOST_CHECK
(
opts
.args.empty());
109
BOOST_CHECK_EQUAL
(
opts
.fruit.size(), 1);
110
BOOST_CHECK_EQUAL
(
opts
.fruit.at(0),
"apple"
sv
);
111
BOOST_CHECK_EQUAL
(
opts
.veg.size(), 1);
112
BOOST_CHECK_EQUAL
(
opts
.veg.at(0),
"carrot"
sv
);
113
BOOST_CHECK
(!
opts
.blend);
114
}
115
{
116
// Empty option value.
117
Opts
opts
;
118
Argv<4>
argv
{
"-f"
,
""
,
"-v"
,
""
};
119
get_opts
(
argv
.size(),
argv
.data(),
opts
);
120
121
BOOST_CHECK
(
opts
.args.empty());
122
BOOST_CHECK_EQUAL
(
opts
.fruit.size(), 1);
123
BOOST_CHECK
(
opts
.fruit.at(0).empty());
124
BOOST_CHECK_EQUAL
(
opts
.veg.size(), 1);
125
BOOST_CHECK
(
opts
.veg.at(0).empty());
126
BOOST_CHECK
(!
opts
.blend);
127
}
128
{
129
// Missing option value.
130
Opts
opts
;
131
Argv<1>
argv
{
"-v"
};
132
BOOST_CHECK_THROW
(
get_opts
(
argv
.size(),
argv
.data(),
opts
), std::runtime_error);
133
}
134
}
135
136
BOOST_AUTO_TEST_CASE
(
ArgvMultiShortOptCase
)
137
{
138
{
139
Opts
opts
;
140
Argv<2>
argv
{
"-fapple"
,
"-fbanana"
};
141
get_opts
(
argv
.size(),
argv
.data(),
opts
);
142
143
BOOST_CHECK
(
opts
.args.empty());
144
BOOST_CHECK_EQUAL
(
opts
.fruit.size(), 2);
145
BOOST_CHECK_EQUAL
(
opts
.fruit.at(0),
"apple"
sv
);
146
BOOST_CHECK_EQUAL
(
opts
.fruit.at(1),
"banana"
sv
);
147
BOOST_CHECK
(
opts
.veg.empty());
148
BOOST_CHECK
(!
opts
.blend);
149
}
150
{
151
Opts
opts
;
152
Argv<4>
argv
{
"-v"
,
"broccoli"
,
"-v"
,
"carrot"
};
153
get_opts
(
argv
.size(),
argv
.data(),
opts
);
154
155
BOOST_CHECK
(
opts
.args.empty());
156
BOOST_CHECK
(
opts
.fruit.empty());
157
BOOST_CHECK_EQUAL
(
opts
.veg.size(), 2);
158
BOOST_CHECK_EQUAL
(
opts
.veg.at(0),
"broccoli"
sv
);
159
BOOST_CHECK_EQUAL
(
opts
.veg.at(1),
"carrot"
sv
);
160
BOOST_CHECK
(!
opts
.blend);
161
}
162
}
163
164
BOOST_AUTO_TEST_CASE
(
ArgvLongOptCase
)
165
{
166
{
167
Opts
opts
;
168
Argv<2>
argv
{
"--fruit=apple"
,
"--veg=carrot"
};
169
get_opts
(
argv
.size(),
argv
.data(),
opts
);
170
171
BOOST_CHECK
(
opts
.args.empty());
172
BOOST_CHECK_EQUAL
(
opts
.fruit.size(), 1);
173
BOOST_CHECK_EQUAL
(
opts
.fruit.at(0),
"apple"
sv
);
174
BOOST_CHECK_EQUAL
(
opts
.veg.size(), 1);
175
BOOST_CHECK_EQUAL
(
opts
.veg.at(0),
"carrot"
sv
);
176
BOOST_CHECK
(!
opts
.blend);
177
}
178
{
179
Opts
opts
;
180
Argv<4>
argv
{
"--veg"
,
"carrot"
,
"--fruit"
,
"apple"
};
181
get_opts
(
argv
.size(),
argv
.data(),
opts
);
182
183
BOOST_CHECK
(
opts
.args.empty());
184
BOOST_CHECK_EQUAL
(
opts
.fruit.size(), 1);
185
BOOST_CHECK_EQUAL
(
opts
.fruit.at(0),
"apple"
sv
);
186
BOOST_CHECK_EQUAL
(
opts
.veg.size(), 1);
187
BOOST_CHECK_EQUAL
(
opts
.veg.at(0),
"carrot"
sv
);
188
BOOST_CHECK
(!
opts
.blend);
189
}
190
{
191
// Empty option value.
192
Opts
opts
;
193
Argv<2>
argv
{
"--fruit="
,
"--veg="
};
194
get_opts
(
argv
.size(),
argv
.data(),
opts
);
195
196
BOOST_CHECK
(
opts
.args.empty());
197
BOOST_CHECK_EQUAL
(
opts
.fruit.size(), 1);
198
BOOST_CHECK
(
opts
.fruit.at(0).empty());
199
BOOST_CHECK_EQUAL
(
opts
.veg.size(), 1);
200
BOOST_CHECK
(
opts
.veg.at(0).empty());
201
BOOST_CHECK
(!
opts
.blend);
202
}
203
{
204
// Missing option value.
205
Opts
opts
;
206
Argv<1>
argv
{
"--veg"
};
207
BOOST_CHECK_THROW
(
get_opts
(
argv
.size(),
argv
.data(),
opts
), std::runtime_error);
208
}
209
}
210
211
BOOST_AUTO_TEST_CASE
(
ArgvMultiLongOptCase
)
212
{
213
{
214
Opts
opts
;
215
Argv<2>
argv
{
"--fruit=apple"
,
"--fruit=banana"
};
216
get_opts
(
argv
.size(),
argv
.data(),
opts
);
217
218
BOOST_CHECK
(
opts
.args.empty());
219
BOOST_CHECK_EQUAL
(
opts
.fruit.size(), 2);
220
BOOST_CHECK_EQUAL
(
opts
.fruit.at(0),
"apple"
sv
);
221
BOOST_CHECK_EQUAL
(
opts
.fruit.at(1),
"banana"
sv
);
222
BOOST_CHECK
(
opts
.veg.empty());
223
BOOST_CHECK
(!
opts
.blend);
224
}
225
{
226
Opts
opts
;
227
Argv<4>
argv
{
"--veg"
,
"broccoli"
,
"--veg"
,
"carrot"
};
228
get_opts
(
argv
.size(),
argv
.data(),
opts
);
229
230
BOOST_CHECK
(
opts
.args.empty());
231
BOOST_CHECK
(
opts
.fruit.empty());
232
BOOST_CHECK_EQUAL
(
opts
.veg.size(), 2);
233
BOOST_CHECK_EQUAL
(
opts
.veg.at(0),
"broccoli"
sv
);
234
BOOST_CHECK_EQUAL
(
opts
.veg.at(1),
"carrot"
sv
);
235
BOOST_CHECK
(!
opts
.blend);
236
}
237
}
238
239
BOOST_AUTO_TEST_CASE
(
ArgvSwitchCase
)
240
{
241
{
242
Opts
opts
;
243
Argv<1>
argv
{
"-b"
};
244
get_opts
(
argv
.size(),
argv
.data(),
opts
);
245
246
BOOST_CHECK
(
opts
.args.empty());
247
BOOST_CHECK
(
opts
.fruit.empty());
248
BOOST_CHECK
(
opts
.veg.empty());
249
BOOST_CHECK
(
opts
.blend);
250
}
251
{
252
Opts
opts
;
253
Argv<1>
argv
{
"--blend"
};
254
get_opts
(
argv
.size(),
argv
.data(),
opts
);
255
256
BOOST_CHECK
(
opts
.args.empty());
257
BOOST_CHECK
(
opts
.fruit.empty());
258
BOOST_CHECK
(
opts
.veg.empty());
259
BOOST_CHECK
(
opts
.blend);
260
}
261
{
262
// Unexpected switch value.
263
Opts
opts
;
264
Argv<1>
argv
{
"-b123"
};
265
BOOST_CHECK_THROW
(
get_opts
(
argv
.size(),
argv
.data(),
opts
), std::runtime_error);
266
}
267
{
268
// Unexpected switch value.
269
Opts
opts
;
270
Argv<1>
argv
{
"--blend=123"
};
271
BOOST_CHECK_THROW
(
get_opts
(
argv
.size(),
argv
.data(),
opts
), std::runtime_error);
272
}
273
}
274
275
BOOST_AUTO_TEST_SUITE_END
()
Argv.hpp
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(ArgvEmptyCase)
Definition
Argv.ut.cpp:60
BOOST_CHECK_EQUAL
BOOST_CHECK_EQUAL(v.size(), 10U)
toolbox::ArgvLexer
Definition
Argv.hpp:54
toolbox::util::ArgvLexer::opt
std::string_view opt() const noexcept
Definition
Argv.hpp:84
std
STL namespace.
toolbox::util::sv
std::string_view sv
Definition
Tokeniser.hpp:26
toolbox::util::bind
constexpr auto bind() noexcept
Definition
Slot.hpp:92
toolbox
Definition
Benchmark.cpp:26
BOOST_CHECK
BOOST_CHECK(isnan(stod(""sv, numeric_limits< double >::quiet_NaN())))
Generated by
1.9.8