2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <gtest/gtest.h>
24 #include "arser/arser.h"
26 using namespace arser;
31 Prompt(const std::string &command)
33 std::istringstream iss(command);
34 std::vector<std::string> token(std::istream_iterator<std::string>{iss},
35 std::istream_iterator<std::string>());
36 _arg = std::move(token);
37 _argv.reserve(_arg.size());
38 for (const auto &t : _arg)
40 _argv.push_back(const_cast<char *>(t.data()));
43 int argc(void) const { return _argv.size(); }
44 char **argv(void) { return _argv.data(); }
47 std::vector<char *> _argv;
48 std::vector<std::string> _arg;
51 TEST(BasicTest, option)
56 arser.add_argument("--verbose")
58 .help("It provides additional details as to what the executable is doing");
60 Prompt prompt("./executable --verbose");
62 arser.parse(prompt.argc(), prompt.argv());
64 EXPECT_TRUE(arser["--verbose"]);
65 EXPECT_TRUE(arser.get<bool>("--verbose"));
68 TEST(BasicTest, OptionalArgument)
73 arser.add_argument("--volume")
75 .type(arser::DataType::INT32)
76 .help("Set a volume as you provided.");
77 arser.add_argument("--frequency")
79 .type(arser::DataType::FLOAT)
80 .help("Set a frequency as you provided.");
82 Prompt prompt("./radio --volume 5 --frequency 128.5");
84 arser.parse(prompt.argc(), prompt.argv());
86 EXPECT_TRUE(arser["--volume"]);
87 EXPECT_EQ(5, arser.get<int>("--volume"));
89 EXPECT_TRUE(arser["--frequency"]);
90 EXPECT_FLOAT_EQ(128.5, arser.get<float>("--frequency"));
92 EXPECT_FALSE(arser["--price"]);
93 EXPECT_THROW(arser.get<bool>("--volume"), std::runtime_error);
96 TEST(BasicTest, NonRequiredOptionalArgument_NEG)
101 arser.add_argument("--weight")
103 .type(arser::DataType::INT32)
104 .help("Set a volume as you provided.");
106 Prompt prompt("./radio"); // empty argument
108 arser.parse(prompt.argc(), prompt.argv());
110 EXPECT_FALSE(arser["--volume"]);
111 EXPECT_THROW(arser.get<int>("--weight"), std::runtime_error);
114 TEST(BasicTest, RequiredOptionalArgument_NEG)
119 arser.add_argument("--volume")
121 .type(arser::DataType::INT32)
123 .help("Set a volume as you provided.");
125 Prompt prompt("./radio");
126 /* act */ /* assert */
127 EXPECT_THROW(arser.parse(prompt.argc(), prompt.argv()), std::runtime_error);
130 TEST(BasicTest, OptionalMultipleArgument)
135 arser.add_argument("--add").nargs(2).type(arser::DataType::INT32_VEC).help("Add two numbers.");
137 Prompt prompt("./calculator --add 3 5");
139 arser.parse(prompt.argc(), prompt.argv());
141 EXPECT_TRUE(arser["--add"]);
142 std::vector<int> values = arser.get<std::vector<int>>("--add");
143 EXPECT_EQ(3, values.at(0));
144 EXPECT_EQ(5, values.at(1));
146 EXPECT_THROW(arser.get<std::vector<float>>("--add"), std::runtime_error);
149 TEST(BasicTest, MultipleOptionalArgument)
154 arser.add_argument("--input_path")
156 .type(arser::DataType::STR)
157 .help("input path of this program.")
159 arser.add_argument("--output_path")
161 .type(arser::DataType::STR)
162 .help("output path of this program.")
164 arser.add_argument("--training_data")
166 .type(arser::DataType::INT32_VEC)
167 .help("give traning data to this program.")
170 Prompt prompt("./ml --input_path /I/am/in.put --output_path I/am/out.put "
171 "--training_data 2 43 234 3 334");
173 arser.parse(prompt.argc(), prompt.argv());
175 EXPECT_TRUE(arser["--input_path"]);
176 EXPECT_EQ("/I/am/in.put", arser.get<std::string>("--input_path"));
177 EXPECT_TRUE(arser["--output_path"]);
178 EXPECT_EQ("I/am/out.put", arser.get<std::string>("--output_path"));
179 EXPECT_TRUE(arser["--training_data"]);
180 std::vector<int32_t> data = arser.get<std::vector<int32_t>>("--training_data");
181 EXPECT_EQ(2, data.at(0));
182 EXPECT_EQ(43, data.at(1));
183 EXPECT_EQ(234, data.at(2));
184 EXPECT_EQ(3, data.at(3));
185 EXPECT_EQ(334, data.at(4));
188 TEST(BasicTest, MultipleFloatValue)
193 arser.add_argument("--add_float")
195 .type(arser::DataType::FLOAT_VEC)
196 .help("Add two float numbers.");
198 Prompt prompt("./calculator --add_float 3.2 5.4");
200 arser.parse(prompt.argc(), prompt.argv());
202 EXPECT_TRUE(arser["--add_float"]);
203 std::vector<float> values = arser.get<std::vector<float>>("--add_float");
204 EXPECT_FLOAT_EQ(3.2, values.at(0));
205 EXPECT_FLOAT_EQ(5.4, values.at(1));
207 EXPECT_THROW(arser.get<std::vector<int>>("--add_float"), std::runtime_error);
210 TEST(BasicTest, MultipleStringValue)
215 arser.add_argument("--three_color")
217 .type(arser::DataType::STR_VEC)
218 .help("insert your three favorite color");
220 Prompt prompt("./color_factory --three_color red blue yellow");
222 arser.parse(prompt.argc(), prompt.argv());
224 EXPECT_TRUE(arser["--three_color"]);
225 std::vector<std::string> values = arser.get<std::vector<std::string>>("--three_color");
226 EXPECT_EQ("red", values.at(0));
227 EXPECT_EQ("blue", values.at(1));
228 EXPECT_EQ("yellow", values.at(2));
230 EXPECT_THROW(arser.get<std::vector<std::string>>("--color"), std::runtime_error);
233 void printBiography(void) { std::cerr << "When I was young.." << std::endl; }
235 TEST(BasicTest, ExitWithFunctionCall)
240 arser.add_argument("--history").help("Show history and exit").exit_with(printBiography);
242 arser.add_argument("--name").nargs(1).type(arser::DataType::STR).help("Name your hero");
244 Prompt prompt("./hero --history");
245 /* act */ /* assert */
246 EXPECT_EXIT(arser.parse(prompt.argc(), prompt.argv()), testing::ExitedWithCode(0),
247 "When I was young..");
250 void printVersion(std::string version) { std::cerr << "arser version : " << version << std::endl; }
252 TEST(BasicTest, ExitWithFunctionCallWithBind)
257 arser.add_argument("--version")
258 .help("Show version and exit")
259 .exit_with(std::bind(printVersion, "1.2.0"));
261 Prompt prompt("./arser --version");
262 /* act */ /* assert */
263 EXPECT_EXIT(arser.parse(prompt.argc(), prompt.argv()), testing::ExitedWithCode(0),
264 "arser version : 1.2.0");
267 TEST(BasicTest, ExitWithFunctionCallWithLamda)
272 arser.add_argument("--shutdown").help("Shut down your computer").exit_with([](void) {
273 std::cerr << "Good bye.." << std::endl;
276 arser.add_argument("OS").nargs(1).type(arser::DataType::STR).help("The OS you want to boot");
278 Prompt prompt("./computer --shutdown");
279 /* act */ /* assert */
280 EXPECT_EXIT(arser.parse(prompt.argc(), prompt.argv()), testing::ExitedWithCode(0), "Good bye..");
283 TEST(BasicTest, DefaultValue)
288 arser.add_argument("--delivery")
290 .type(arser::DataType::STR_VEC)
291 .default_value("pizza", "chicken", "hamburger")
292 .help("Enter three foods that you want to deliver");
293 arser.add_argument("--assistant")
294 .type(arser::DataType::STR)
295 .default_value("Bixby")
296 .help("Enter name of your assistant");
297 arser.add_argument("--sound")
298 .type(arser::DataType::BOOL)
301 .help("Sound on/off");
302 arser.add_argument("--number")
303 .type(arser::DataType::INT32_VEC)
305 .default_value(1, 2, 3, 4)
306 .help("Enter the number that you want to call");
307 arser.add_argument("--time")
308 .type(arser::DataType::INT32_VEC)
310 .default_value(0, 0, 0)
311 .help("Current time(H/M/S)");
312 arser.add_argument("--name")
313 .type(arser::DataType::STR)
315 .default_value("no name")
316 .help("Enter your name");
318 Prompt prompt("/phone --time 1 52 34 --name arser");
320 arser.parse(prompt.argc(), prompt.argv());
322 // 3 strings, no argument
323 std::vector<std::string> delivery = arser.get<std::vector<std::string>>("--delivery");
324 EXPECT_EQ("pizza", delivery.at(0));
325 EXPECT_EQ("chicken", delivery.at(1));
326 EXPECT_EQ("hamburger", delivery.at(2));
327 // 1 string, no argument
328 EXPECT_EQ("Bixby", arser.get<std::string>("--assistant"));
329 // 1 bool, no argument
330 EXPECT_EQ(true, arser.get<bool>("--sound"));
331 // 4 integer, no argument
332 std::vector<int> number = arser.get<std::vector<int>>("--number");
333 EXPECT_EQ(1, number.at(0));
334 EXPECT_EQ(2, number.at(1));
335 EXPECT_EQ(3, number.at(2));
336 EXPECT_EQ(4, number.at(3));
337 // 3 integer, 3 arguments
338 std::vector<int> time = arser.get<std::vector<int>>("--time");
339 EXPECT_EQ(1, time.at(0));
340 EXPECT_EQ(52, time.at(1));
341 EXPECT_EQ(34, time.at(2));
342 // 1 string, 1 argument
343 EXPECT_EQ("arser", arser.get<std::string>("--name"));
346 TEST(BasicTest, shortOption)
351 arser.add_argument("--input_path", "-i")
353 .type(arser::DataType::STR)
354 .help("input path of this program.")
356 arser.add_argument("--output_path", "-o")
358 .type(arser::DataType::STR)
359 .help("output path of this program.")
362 Prompt prompt("./driver -i /I/am/in.put --output_path I/am/out.put");
364 arser.parse(prompt.argc(), prompt.argv());
366 EXPECT_TRUE(arser["--input_path"]);
367 EXPECT_EQ("/I/am/in.put", arser.get<std::string>("--input_path"));
368 EXPECT_TRUE(arser["--output_path"]);
369 EXPECT_EQ("I/am/out.put", arser.get<std::string>("--output_path"));
372 TEST(BasicTest, shortMultipleOption)
377 arser.add_argument("--input_path", "-i", "--input", "--in")
379 .type(arser::DataType::STR)
380 .help("input path of this program.")
382 arser.add_argument("--output_path", "-o")
384 .type(arser::DataType::STR)
385 .help("output path of this program.")
388 Prompt prompt("./driver --in /I/am/in.put -o I/am/out.put");
390 arser.parse(prompt.argc(), prompt.argv());
392 EXPECT_TRUE(arser["--input"]);
393 EXPECT_EQ("/I/am/in.put", arser.get<std::string>("--input"));
394 EXPECT_TRUE(arser["--output_path"]);
395 EXPECT_EQ("I/am/out.put", arser.get<std::string>("--output_path"));
398 TEST(BasicTest, OptWithRequiredDuplicate_NEG)
403 arser.add_argument("--input_path", "-i", "--input", "--in")
405 .type(arser::DataType::STR)
406 .help("input path of this program.")
408 arser.add_argument("--output_path", "-o")
410 .type(arser::DataType::STR)
411 .help("output path of this program.")
414 Prompt prompt("./driver --in /I/am/in.put -o I/am/out.put -i /I/am/duplicate");
415 /* act */ /* assert */
416 EXPECT_THROW(arser.parse(prompt.argc(), prompt.argv()), std::runtime_error);
419 TEST(BasicTest, OptWithNonRequiredDuplicate)
424 arser.add_argument("--input_path", "-i", "--input", "--in")
426 .type(arser::DataType::STR)
427 .help("input path of this program.");
429 arser.add_argument("--output_path", "-o")
431 .type(arser::DataType::STR)
432 .help("output path of this program.")
435 Prompt prompt("./driver --in /I/am/in.put -o I/am/out.put -i /I/am/duplicate");
437 arser.parse(prompt.argc(), prompt.argv());
439 EXPECT_TRUE(arser["--input"]);
440 EXPECT_EQ("/I/am/duplicate", arser.get<std::string>("--input"));
441 EXPECT_TRUE(arser["--output_path"]);
442 EXPECT_EQ("I/am/out.put", arser.get<std::string>("--output_path"));
445 TEST(BasicTest, AccumulateVectorOptions)
450 arser.add_argument("--specify").nargs(3).accumulated(true).type(arser::DataType::STR_VEC);
452 Prompt prompt("./driver --specify a b c --specify 1 2 3");
454 arser.parse(prompt.argc(), prompt.argv());
456 EXPECT_TRUE(arser["--specify"]);
458 auto specify = arser.get<std::vector<std::vector<std::string>>>("--specify");
459 auto first = specify[0];
460 EXPECT_EQ("a", first.at(0));
461 EXPECT_EQ("b", first.at(1));
462 EXPECT_EQ("c", first.at(2));
463 auto second = specify[1];
464 EXPECT_EQ("1", second.at(0));
465 EXPECT_EQ("2", second.at(1));
466 EXPECT_EQ("3", second.at(2));
469 TEST(BasicTest, AccumulateScalarOptions)
474 arser.add_argument("--specify").nargs(1).accumulated(true).type(arser::DataType::FLOAT);
476 Prompt prompt("./driver --specify 1 --specify 2");
478 arser.parse(prompt.argc(), prompt.argv());
480 EXPECT_TRUE(arser["--specify"]);
482 auto specify = arser.get<std::vector<float>>("--specify");
483 EXPECT_EQ(1, specify.at(0));
484 EXPECT_EQ(2, specify.at(1));
487 TEST(BasicTest, AccumulateScalarOptions_WrongType_NEG)
492 arser.add_argument("--specify").nargs(1).accumulated(true).type(arser::DataType::FLOAT);
494 Prompt prompt("./driver --specify 1 --specify 2");
496 arser.parse(prompt.argc(), prompt.argv());
498 EXPECT_TRUE(arser["--specify"]);
500 EXPECT_THROW(arser.get<float>("--specify"), std::runtime_error);