Imported Upstream version 1.18.0
[platform/core/ml/nnfw.git] / compiler / arser / tests / arser.test.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
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
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <iterator>
18 #include <sstream>
19 #include <string>
20 #include <vector>
21
22 #include <gtest/gtest.h>
23
24 #include "arser/arser.h"
25
26 using namespace arser;
27
28 class Prompt
29 {
30 public:
31   Prompt(const std::string &command)
32   {
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)
39     {
40       _argv.push_back(const_cast<char *>(t.data()));
41     }
42   }
43   int argc(void) const { return _argv.size(); }
44   char **argv(void) { return _argv.data(); }
45
46 private:
47   std::vector<char *> _argv;
48   std::vector<std::string> _arg;
49 };
50
51 TEST(BasicTest, option)
52 {
53   /* arrange */
54   Arser arser;
55
56   arser.add_argument("--verbose")
57     .nargs(0)
58     .help("It provides additional details as to what the executable is doing");
59
60   Prompt prompt("./executable --verbose");
61   /* act */
62   arser.parse(prompt.argc(), prompt.argv());
63   /* assert */
64   EXPECT_TRUE(arser["--verbose"]);
65   EXPECT_TRUE(arser.get<bool>("--verbose"));
66 }
67
68 TEST(BasicTest, OptionalArgument)
69 {
70   /* arrange */
71   Arser arser;
72
73   arser.add_argument("--volume")
74     .nargs(1)
75     .type(arser::DataType::INT32)
76     .help("Set a volume as you provided.");
77   arser.add_argument("--frequency")
78     .nargs(1)
79     .type(arser::DataType::FLOAT)
80     .help("Set a frequency as you provided.");
81
82   Prompt prompt("./radio --volume 5 --frequency 128.5");
83   /* act */
84   arser.parse(prompt.argc(), prompt.argv());
85   /* assert */
86   EXPECT_TRUE(arser["--volume"]);
87   EXPECT_EQ(5, arser.get<int>("--volume"));
88
89   EXPECT_TRUE(arser["--frequency"]);
90   EXPECT_FLOAT_EQ(128.5, arser.get<float>("--frequency"));
91
92   EXPECT_FALSE(arser["--price"]);
93   EXPECT_THROW(arser.get<bool>("--volume"), std::runtime_error);
94 }
95
96 TEST(BasicTest, NonRequiredOptionalArgument_NEG)
97 {
98   /* arrange */
99   Arser arser;
100
101   arser.add_argument("--weight")
102     .nargs(1)
103     .type(arser::DataType::INT32)
104     .help("Set a volume as you provided.");
105
106   Prompt prompt("./radio"); // empty argument
107   /* act */
108   arser.parse(prompt.argc(), prompt.argv());
109   /* assert */
110   EXPECT_FALSE(arser["--volume"]);
111   EXPECT_THROW(arser.get<int>("--weight"), std::runtime_error);
112 }
113
114 TEST(BasicTest, RequiredOptionalArgument_NEG)
115 {
116   /* arrange */
117   Arser arser;
118
119   arser.add_argument("--volume")
120     .nargs(1)
121     .type(arser::DataType::INT32)
122     .required()
123     .help("Set a volume as you provided.");
124
125   Prompt prompt("./radio");
126   /* act */ /* assert */
127   EXPECT_THROW(arser.parse(prompt.argc(), prompt.argv()), std::runtime_error);
128 }
129
130 TEST(BasicTest, OptionalMultipleArgument)
131 {
132   /* arrange */
133   Arser arser;
134
135   arser.add_argument("--add").nargs(2).type(arser::DataType::INT32_VEC).help("Add two numbers.");
136
137   Prompt prompt("./calculator --add 3 5");
138   /* act */
139   arser.parse(prompt.argc(), prompt.argv());
140   /* assert */
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));
145
146   EXPECT_THROW(arser.get<std::vector<float>>("--add"), std::runtime_error);
147 }
148
149 TEST(BasicTest, MultipleOptionalArgument)
150 {
151   /* arrange */
152   Arser arser;
153
154   arser.add_argument("--input_path")
155     .nargs(1)
156     .type(arser::DataType::STR)
157     .help("input path of this program.")
158     .required();
159   arser.add_argument("--output_path")
160     .nargs(1)
161     .type(arser::DataType::STR)
162     .help("output path of this program.")
163     .required(true);
164   arser.add_argument("--training_data")
165     .nargs(5)
166     .type(arser::DataType::INT32_VEC)
167     .help("give traning data to this program.")
168     .required();
169
170   Prompt prompt("./ml --input_path /I/am/in.put --output_path I/am/out.put "
171                 "--training_data 2 43 234 3 334");
172   /* act */
173   arser.parse(prompt.argc(), prompt.argv());
174   /* assert */
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));
186 }
187
188 TEST(BasicTest, MultipleFloatValue)
189 {
190   /* arrange */
191   Arser arser;
192
193   arser.add_argument("--add_float")
194     .nargs(2)
195     .type(arser::DataType::FLOAT_VEC)
196     .help("Add two float numbers.");
197
198   Prompt prompt("./calculator --add_float 3.2 5.4");
199   /* act */
200   arser.parse(prompt.argc(), prompt.argv());
201   /* assert */
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));
206
207   EXPECT_THROW(arser.get<std::vector<int>>("--add_float"), std::runtime_error);
208 }
209
210 TEST(BasicTest, MultipleStringValue)
211 {
212   /* arrange */
213   Arser arser;
214
215   arser.add_argument("--three_color")
216     .nargs(3)
217     .type(arser::DataType::STR_VEC)
218     .help("insert your three favorite color");
219
220   Prompt prompt("./color_factory --three_color red blue yellow");
221   /* act */
222   arser.parse(prompt.argc(), prompt.argv());
223   /* assert */
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));
229
230   EXPECT_THROW(arser.get<std::vector<std::string>>("--color"), std::runtime_error);
231 }
232
233 void printBiography(void) { std::cerr << "When I was young.." << std::endl; }
234
235 TEST(BasicTest, ExitWithFunctionCall)
236 {
237   /* arrange */
238   Arser arser;
239
240   arser.add_argument("--history").help("Show history and exit").exit_with(printBiography);
241
242   arser.add_argument("--name").nargs(1).type(arser::DataType::STR).help("Name your hero");
243
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..");
248 }
249
250 void printVersion(std::string version) { std::cerr << "arser version : " << version << std::endl; }
251
252 TEST(BasicTest, ExitWithFunctionCallWithBind)
253 {
254   /* arrange */
255   Arser arser;
256
257   arser.add_argument("--version")
258     .help("Show version and exit")
259     .exit_with(std::bind(printVersion, "1.2.0"));
260
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");
265 }
266
267 TEST(BasicTest, ExitWithFunctionCallWithLamda)
268 {
269   /* arrange */
270   Arser arser;
271
272   arser.add_argument("--shutdown").help("Shut down your computer").exit_with([](void) {
273     std::cerr << "Good bye.." << std::endl;
274   });
275
276   arser.add_argument("OS").nargs(1).type(arser::DataType::STR).help("The OS you want to boot");
277
278   Prompt prompt("./computer --shutdown");
279   /* act */ /* assert */
280   EXPECT_EXIT(arser.parse(prompt.argc(), prompt.argv()), testing::ExitedWithCode(0), "Good bye..");
281 }
282
283 TEST(BasicTest, DefaultValue)
284 {
285   /* arrange */
286   Arser arser;
287
288   arser.add_argument("--delivery")
289     .nargs(3)
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)
299     .nargs(1)
300     .default_value(true)
301     .help("Sound on/off");
302   arser.add_argument("--number")
303     .type(arser::DataType::INT32_VEC)
304     .nargs(4)
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)
309     .nargs(3)
310     .default_value(0, 0, 0)
311     .help("Current time(H/M/S)");
312   arser.add_argument("--name")
313     .type(arser::DataType::STR)
314     .nargs(1)
315     .default_value("no name")
316     .help("Enter your name");
317
318   Prompt prompt("/phone --time 1 52 34 --name arser");
319   /* act */
320   arser.parse(prompt.argc(), prompt.argv());
321   /* assert */
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"));
344 }
345
346 TEST(BasicTest, shortOption)
347 {
348   /* arrange */
349   Arser arser;
350
351   arser.add_argument("--input_path", "-i")
352     .nargs(1)
353     .type(arser::DataType::STR)
354     .help("input path of this program.")
355     .required();
356   arser.add_argument("--output_path", "-o")
357     .nargs(1)
358     .type(arser::DataType::STR)
359     .help("output path of this program.")
360     .required(true);
361
362   Prompt prompt("./driver -i /I/am/in.put --output_path I/am/out.put");
363   /* act */
364   arser.parse(prompt.argc(), prompt.argv());
365   /* assert */
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"));
370 }
371
372 TEST(BasicTest, shortMultipleOption)
373 {
374   /* arrange */
375   Arser arser;
376
377   arser.add_argument("--input_path", "-i", "--input", "--in")
378     .nargs(1)
379     .type(arser::DataType::STR)
380     .help("input path of this program.")
381     .required();
382   arser.add_argument("--output_path", "-o")
383     .nargs(1)
384     .type(arser::DataType::STR)
385     .help("output path of this program.")
386     .required(true);
387
388   Prompt prompt("./driver --in /I/am/in.put -o I/am/out.put");
389   /* act */
390   arser.parse(prompt.argc(), prompt.argv());
391   /* assert */
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"));
396 }
397
398 TEST(BasicTest, OptWithRequiredDuplicate_NEG)
399 {
400   /* arrange */
401   Arser arser;
402
403   arser.add_argument("--input_path", "-i", "--input", "--in")
404     .nargs(1)
405     .type(arser::DataType::STR)
406     .help("input path of this program.")
407     .required();
408   arser.add_argument("--output_path", "-o")
409     .nargs(1)
410     .type(arser::DataType::STR)
411     .help("output path of this program.")
412     .required(true);
413
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);
417 }
418
419 TEST(BasicTest, OptWithNonRequiredDuplicate)
420 {
421   /* arrange */
422   Arser arser;
423
424   arser.add_argument("--input_path", "-i", "--input", "--in")
425     .nargs(1)
426     .type(arser::DataType::STR)
427     .help("input path of this program.");
428   /* .required() */
429   arser.add_argument("--output_path", "-o")
430     .nargs(1)
431     .type(arser::DataType::STR)
432     .help("output path of this program.")
433     .required(true);
434
435   Prompt prompt("./driver --in /I/am/in.put -o I/am/out.put -i /I/am/duplicate");
436   /* act */
437   arser.parse(prompt.argc(), prompt.argv());
438   /* assert */
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"));
443 }
444
445 TEST(BasicTest, AccumulateVectorOptions)
446 {
447   /* arrange */
448   Arser arser;
449
450   arser.add_argument("--specify").nargs(3).accumulated(true).type(arser::DataType::STR_VEC);
451
452   Prompt prompt("./driver --specify a b c --specify 1 2 3");
453   /* act */
454   arser.parse(prompt.argc(), prompt.argv());
455   /* assert */
456   EXPECT_TRUE(arser["--specify"]);
457
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));
467 }
468
469 TEST(BasicTest, AccumulateScalarOptions)
470 {
471   /* arrange */
472   Arser arser;
473
474   arser.add_argument("--specify").nargs(1).accumulated(true).type(arser::DataType::FLOAT);
475
476   Prompt prompt("./driver --specify 1 --specify 2");
477   /* act */
478   arser.parse(prompt.argc(), prompt.argv());
479   /* assert */
480   EXPECT_TRUE(arser["--specify"]);
481
482   auto specify = arser.get<std::vector<float>>("--specify");
483   EXPECT_EQ(1, specify.at(0));
484   EXPECT_EQ(2, specify.at(1));
485 }
486
487 TEST(BasicTest, AccumulateScalarOptions_WrongType_NEG)
488 {
489   /* arrange */
490   Arser arser;
491
492   arser.add_argument("--specify").nargs(1).accumulated(true).type(arser::DataType::FLOAT);
493
494   Prompt prompt("./driver --specify 1 --specify 2");
495   /* act */
496   arser.parse(prompt.argc(), prompt.argv());
497   /* assert */
498   EXPECT_TRUE(arser["--specify"]);
499
500   EXPECT_THROW(arser.get<float>("--specify"), std::runtime_error);
501 }