1 // ==========================================================================
2 //                                 arg_parse
3 // ==========================================================================
4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 //       notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above copyright
13 //       notice, this list of conditions and the following disclaimer in the
14 //       documentation and/or other materials provided with the distribution.
15 //     * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 //       its contributors may be used to endorse or promote products derived
17 //       from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32 // Author: Stephan Aiche <stephan.aiche@fu-berlin.de>
33 // ==========================================================================
34 
35 #ifndef SEQAN_TESTS_ARG_PARSE_TEST_ARG_PARSE_H_
36 #define SEQAN_TESTS_ARG_PARSE_TEST_ARG_PARSE_H_
37 
38 #include <seqan/basic.h>
39 #include <seqan/sequence.h>
40 
41 
42 #include <seqan/arg_parse.h> // Header under test
43 
44 #include <seqan/basic.h>
45 #include <iostream>
46 
47 using namespace std;
48 
49 const char * A_INT_0 = "test";
50 const char * A_INT_1 = "-i";
51 const char * A_INT_2 = "--integer";
52 const char * A_INT_3 = "1";
53 const char * A_INT_5 = "3000000000";  // too large!
54 
55 const char * A_INT64_0 = "test";
56 const char * A_INT64_1 = "-i";
57 const char * A_INT64_2 = "--int64";
58 const char * A_INT64_3 = "3000000000";
59 const char * A_INT64_5 = "not-an-int";
60 
61 const char * A_DOUBLE_0 = "test";
62 const char * A_DOUBLE_1 = "-d";
63 const char * A_DOUBLE_2 = "--double";
64 const char * A_DOUBLE_3 = "1.56";
65 const char * A_DOUBLE_5 = "not-a-double";
66 const char * A_DOUBLE_6 = "6.0221418e23";
67 
68 const char * A_STRING_0 = "test";
69 const char * A_STRING_1 = "-s";
70 const char * A_STRING_2 = "--string";
71 const char * A_STRING_3 = "this-is-a-string-value";
72 
73 const char * A_BOOL = "test-boolean-flags";
74 const char * A_BOOL_1 = "-b";
75 const char * A_BOOL_2 = "-c";
76 const char * A_BOOL_3 = "-bc";
77 const char * A_BOOL_4 = "-cb";
78 
79 const char * A_BOOL_ARG = "test-boolean-argument";
80 const char * A_BOOL_ARG_SHORT = "-b";
81 const char * A_BOOL_ARG_OFF = "OFF";
82 const char * A_BOOL_ARG_ON  = "ON";
83 
84 const char * A_IN_FILE_0 = "test";
85 const char * A_IN_FILE_1 = "-i";
86 const char * A_IN_FILE_2 = "--in";
87 const char * A_IN_FILE_3 = "input.fasta";
88 
89 const char * A_OUT_FILE_0 = "test";
90 const char * A_OUT_FILE_1 = "-o";
91 const char * A_OUT_FILE_2 = "--out";
92 const char * A_OUT_FILE_3 = "output.fasta";
93 const char * A_OUT_FILE_4 = "output.tar.gz";
94 const char * A_OUT_FILE_5 = "output.txt";
95 const char * A_OUT_FILE_6 = "--out-file-ext";
96 const char * A_OUT_FILE_7 = "fasta";
97 const char * A_OUT_FILE_8 = "txt";
98 
99 const char * A_ARGUMENT_0 = "test";
100 const char * A_ARGUMENT_1 = "argument1";
101 const char * A_ARGUMENT_2 = "argument2";
102 const char * A_ARGUMENT_3 = "argument3";
103 const char * A_ARGUMENT_INT_4 = "-10";
104 const char * A_ARGUMENT_DOUBLE_5 = "6.0221418e23";
105 
106 const char * A_TUPLE_LIST = "test_tuple_list";
107 const char * A_TUPLE_LIST_L = "-l";
108 const char * A_TUPLE_LIST_L_1 = "10";
109 const char * A_TUPLE_LIST_L_2 =  "20";
110 const char * A_TUPLE_LIST_L_3 =  "30";
111 const char * A_TUPLE_LIST_L_4 =  "40";
112 
113 const char * A_TUPLE_LIST_DL = "-k";
114 const char * A_TUPLE_LIST_DL_1 = "5.1";
115 const char * A_TUPLE_LIST_DL_2 = "6.2";
116 const char * A_TUPLE_LIST_DL_3 = "7.3";
117 const char * A_TUPLE_LIST_DL_4 = "5.5";
118 const char * A_TUPLE_LIST_DL_5 = "6.6";
119 const char * A_TUPLE_LIST_DL_6 = "7.7";
120 
121 namespace seqan {
122 
123 // moved initialization of cmd parser out of the test functions
124 // to have single place to change in case of interface changes
125 // or test extensions
setupDoubleParser(ArgumentParser & parser)126 void setupDoubleParser(ArgumentParser & parser)
127 {
128     addOption(parser, ArgParseOption("d", "double", "set a double option", ArgParseArgument::DOUBLE));
129 }
130 
setupIntegerParser(ArgumentParser & parser)131 void setupIntegerParser(ArgumentParser & parser)
132 {
133     addOption(parser, ArgParseOption("i", "integer", "set an integer option", ArgParseArgument::INTEGER));
134 }
135 
setupInt64Parser(ArgumentParser & parser)136 void setupInt64Parser(ArgumentParser & parser)
137 {
138     addOption(parser, ArgParseOption("i", "int64", "set a 64 bit integer option", ArgParseArgument::INT64));
139 }
140 
setupStringParser(ArgumentParser & parser)141 void setupStringParser(ArgumentParser & parser)
142 {
143     addOption(parser, ArgParseOption("s", "string", "set a string option", ArgParseArgument::STRING, "", true));
144 }
145 
setupInputFileParser(ArgumentParser & parser)146 void setupInputFileParser(ArgumentParser & parser)
147 {
148     addOption(parser, ArgParseOption("i", "in", "set an input file", ArgParseArgument::INPUT_FILE));
149 }
150 
setupOutputFileParser(ArgumentParser & parser)151 void setupOutputFileParser(ArgumentParser & parser)
152 {
153     addOption(parser, ArgParseOption("o", "out", "set an output file", ArgParseArgument::OUTPUT_FILE));
154 }
155 
setupBooleanParser(ArgumentParser & parser)156 void setupBooleanParser(ArgumentParser & parser)
157 {
158     addOption(parser, ArgParseOption("b", "mybool", "set a bool", ArgParseArgument::BOOL));
159 }
160 
SEQAN_DEFINE_TEST(test_unset_value)161 SEQAN_DEFINE_TEST(test_unset_value)
162 {
163     ArgumentParser parser;
164     setupIntegerParser(parser);
165 
166     int argc = 1;
167     const char * argv[1] = {A_INT_0};
168 
169     std::stringstream error_stream;
170     std::stringstream outputStream;
171 
172     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
173     SEQAN_ASSERT_EQ(error_stream.str(), "");
174     SEQAN_ASSERT_EQ(outputStream.str(), "");
175 
176     int integerValue = 584864836;
177     SEQAN_ASSERT(!getOptionValue(integerValue, parser, "integer"));
178     SEQAN_ASSERT_EQ(integerValue, 584864836);
179 }
180 
SEQAN_DEFINE_TEST(test_unset_values)181 SEQAN_DEFINE_TEST(test_unset_values)
182 {
183     ArgumentParser parser;
184     setupIntegerParser(parser);
185 
186     int argc = 1;
187     const char * argv[1] = {A_INT_0};
188 
189     std::stringstream error_stream;
190     std::stringstream outputStream;
191 
192     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
193     SEQAN_ASSERT_EQ(error_stream.str(), "");
194     SEQAN_ASSERT_EQ(outputStream.str(), "");
195 
196     std::vector<std::string> values = getOptionValues(parser, "integer");
197     SEQAN_ASSERT_EQ(values.size(), 0u);
198 }
199 
SEQAN_DEFINE_TEST(test_boolean_argument_on)200 SEQAN_DEFINE_TEST(test_boolean_argument_on)
201 {
202 
203     ArgumentParser parser;
204     setupBooleanParser(parser);
205 
206     int argc = 3;
207     const char * argv[3] = {A_BOOL_ARG, A_BOOL_ARG_SHORT, A_BOOL_ARG_ON};
208 
209     std::stringstream error_stream;
210     std::stringstream outputStream;
211 
212     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
213     SEQAN_ASSERT_EQ(error_stream.str(), "");
214     SEQAN_ASSERT_EQ(outputStream.str(), "");
215 
216     bool booleanValue = 0;
217     SEQAN_ASSERT(getOptionValue(booleanValue, parser, "mybool"));
218     SEQAN_ASSERT_EQ(booleanValue, true);
219 }
220 
SEQAN_DEFINE_TEST(test_boolean_argument_off)221 SEQAN_DEFINE_TEST(test_boolean_argument_off)
222 {
223 
224     ArgumentParser parser;
225     setupBooleanParser(parser);
226 
227     int argc = 3;
228     const char * argv[3] = {A_BOOL_ARG, A_BOOL_ARG_SHORT, A_BOOL_ARG_OFF};
229 
230     std::stringstream error_stream;
231     std::stringstream outputStream;
232 
233     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
234     SEQAN_ASSERT_EQ(error_stream.str(), "");
235     SEQAN_ASSERT_EQ(outputStream.str(), "");
236 
237     bool booleanValue = 1;
238     SEQAN_ASSERT(getOptionValue(booleanValue, parser, "mybool"));
239     SEQAN_ASSERT_EQ(booleanValue, false);
240 }
241 
SEQAN_DEFINE_TEST(test_int_short_argument)242 SEQAN_DEFINE_TEST(test_int_short_argument)
243 {
244 
245     ArgumentParser parser;
246     setupIntegerParser(parser);
247 
248     int argc = 3;
249     const char * argv[3] = {A_INT_0, A_INT_1, A_INT_3};
250 
251     std::stringstream error_stream;
252     std::stringstream outputStream;
253 
254     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
255     SEQAN_ASSERT_EQ(error_stream.str(), "");
256     SEQAN_ASSERT_EQ(outputStream.str(), "");
257 
258     int integerValue = 0;
259     SEQAN_ASSERT(getOptionValue(integerValue, parser, "integer"));
260     SEQAN_ASSERT_EQ(integerValue, 1);
261 }
262 
SEQAN_DEFINE_TEST(test_int_long_argument)263 SEQAN_DEFINE_TEST(test_int_long_argument)
264 {
265 
266     ArgumentParser parser;
267     setupIntegerParser(parser);
268 
269     int argc = 3;
270     const char * argv[3] = {A_INT_0, A_INT_2, A_INT_3};
271 
272     std::stringstream error_stream;
273     std::stringstream outputStream;
274 
275     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
276     SEQAN_ASSERT_EQ(error_stream.str(), "");
277     SEQAN_ASSERT_EQ(outputStream.str(), "");
278 
279     int integerValue = 0;
280     SEQAN_ASSERT(getOptionValue(integerValue, parser, "integer"));
281     SEQAN_ASSERT_EQ(integerValue, 1);
282 }
283 
SEQAN_DEFINE_TEST(test_non_int_argument)284 SEQAN_DEFINE_TEST(test_non_int_argument)
285 {
286 
287     ArgumentParser parser;
288     setupIntegerParser(parser);
289 
290     int argc = 3;
291     const char * argv[3] = {A_INT_0, A_INT_1, A_INT_5};
292 
293     std::stringstream error_stream;
294     std::stringstream outputStream;
295 
296     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
297     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value '3000000000' cannot be casted to integer\n");
298     SEQAN_ASSERT_EQ(outputStream.str(), "");
299 }
300 
SEQAN_DEFINE_TEST(test_int64_short_argument)301 SEQAN_DEFINE_TEST(test_int64_short_argument)
302 {
303 
304     ArgumentParser parser;
305     setupInt64Parser(parser);
306 
307     int argc = 3;
308     const char * argv[3] = {A_INT64_0, A_INT64_1, A_INT64_3};
309 
310     std::stringstream error_stream;
311     std::stringstream outputStream;
312 
313     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
314     SEQAN_ASSERT_EQ(error_stream.str(), "");
315     SEQAN_ASSERT_EQ(outputStream.str(), "");
316 
317     int64_t integerValue = 0;
318     SEQAN_ASSERT(getOptionValue(integerValue, parser, "int64"));
319     SEQAN_ASSERT_EQ(integerValue, 3000000000ll);
320 }
321 
SEQAN_DEFINE_TEST(test_int64_long_argument)322 SEQAN_DEFINE_TEST(test_int64_long_argument)
323 {
324 
325     ArgumentParser parser;
326     setupInt64Parser(parser);
327 
328     int argc = 3;
329     const char * argv[3] = {A_INT64_0, A_INT64_2, A_INT64_3};
330 
331     std::stringstream error_stream;
332     std::stringstream outputStream;
333 
334     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
335     SEQAN_ASSERT_EQ(error_stream.str(), "");
336     SEQAN_ASSERT_EQ(outputStream.str(), "");
337 
338     int64_t integerValue = 0;
339     SEQAN_ASSERT(getOptionValue(integerValue, parser, "int64"));
340     SEQAN_ASSERT_EQ(integerValue, 3000000000ll);
341 }
342 
SEQAN_DEFINE_TEST(test_non_int64_argument)343 SEQAN_DEFINE_TEST(test_non_int64_argument)
344 {
345 
346     ArgumentParser parser;
347     setupInt64Parser(parser);
348 
349     int argc = 3;
350     const char * argv[3] = {A_INT64_0, A_INT64_1, A_INT64_5};
351 
352     std::stringstream error_stream;
353     std::stringstream outputStream;
354 
355     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
356     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value 'not-an-int' cannot be casted to int64\n");
357     SEQAN_ASSERT_EQ(outputStream.str(), "");
358 }
359 
SEQAN_DEFINE_TEST(test_double_short_argument)360 SEQAN_DEFINE_TEST(test_double_short_argument)
361 {
362 
363     ArgumentParser parser;
364     setupDoubleParser(parser);
365 
366     int argc = 3;
367     const char * argv[3] = {A_DOUBLE_0, A_DOUBLE_1, A_DOUBLE_3};
368 
369     std::stringstream error_stream;
370     std::stringstream outputStream;
371 
372     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
373     SEQAN_ASSERT_EQ(error_stream.str(), "");
374     SEQAN_ASSERT_EQ(outputStream.str(), "");
375 
376     double doubleValue = 0.0;
377     SEQAN_ASSERT(getOptionValue(doubleValue, parser, "double"));
378     SEQAN_ASSERT_EQ(doubleValue, 1.56);
379 }
380 
SEQAN_DEFINE_TEST(test_double_long_argument)381 SEQAN_DEFINE_TEST(test_double_long_argument)
382 {
383 
384     ArgumentParser parser;
385     setupDoubleParser(parser);
386 
387     int argc = 3;
388     const char * argv[3] = {A_DOUBLE_0, A_DOUBLE_2, A_DOUBLE_3};
389 
390     std::stringstream error_stream;
391     std::stringstream outputStream;
392 
393     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
394     SEQAN_ASSERT_EQ(error_stream.str(), "");
395     SEQAN_ASSERT_EQ(outputStream.str(), "");
396 
397     double doubleValue = 0.0;
398     SEQAN_ASSERT(getOptionValue(doubleValue, parser, "double"));
399     SEQAN_ASSERT_EQ(doubleValue, 1.56);
400 }
401 
SEQAN_DEFINE_TEST(test_non_double_argument)402 SEQAN_DEFINE_TEST(test_non_double_argument)
403 {
404 
405     ArgumentParser parser;
406     setupDoubleParser(parser);
407 
408     int argc = 3;
409     const char * argv[3] = {A_DOUBLE_0, A_DOUBLE_1, A_DOUBLE_5};
410 
411     std::stringstream error_stream;
412     std::stringstream outputStream;
413 
414     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
415     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value 'not-a-double' cannot be casted to double\n");
416     SEQAN_ASSERT_EQ(outputStream.str(), "");
417 }
418 
SEQAN_DEFINE_TEST(test_double_scientific_notation)419 SEQAN_DEFINE_TEST(test_double_scientific_notation)
420 {
421 
422     ArgumentParser parser;
423     setupDoubleParser(parser);
424 
425     int argc = 3;
426     const char * argv[3] = {A_DOUBLE_0, A_DOUBLE_1, A_DOUBLE_6};
427 
428     std::stringstream error_stream;
429     std::stringstream outputStream;
430 
431     double doubleValue = 0.0;
432     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
433     SEQAN_ASSERT_EQ(error_stream.str(), "");
434     SEQAN_ASSERT_EQ(outputStream.str(), "");
435 
436     SEQAN_ASSERT(getOptionValue(doubleValue, parser, "double"));
437     SEQAN_ASSERT_EQ(doubleValue, 6.0221418e23);
438 }
439 
SEQAN_DEFINE_TEST(test_string_short_argument)440 SEQAN_DEFINE_TEST(test_string_short_argument)
441 {
442 
443     ArgumentParser parser;
444     setupStringParser(parser);
445 
446     int argc = 3;
447     const char * argv[3] = {A_STRING_0, A_STRING_1, A_STRING_3};
448 
449     std::stringstream error_stream;
450     std::stringstream outputStream;
451 
452     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
453     SEQAN_ASSERT_EQ(error_stream.str(), "");
454     SEQAN_ASSERT_EQ(outputStream.str(), "");
455 
456     CharString value;
457     SEQAN_ASSERT(getOptionValue(value, parser, "string"));
458     SEQAN_ASSERT_EQ(value, "this-is-a-string-value");
459 }
460 
SEQAN_DEFINE_TEST(test_string_long_argument)461 SEQAN_DEFINE_TEST(test_string_long_argument)
462 {
463 
464     ArgumentParser parser;
465     setupStringParser(parser);
466 
467     int argc = 3;
468     const char * argv[3] = {A_STRING_0, A_STRING_2, A_STRING_3};
469 
470     std::stringstream error_stream;
471     std::stringstream outputStream;
472     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
473     SEQAN_ASSERT_EQ(error_stream.str(), "");
474     SEQAN_ASSERT_EQ(outputStream.str(), "");
475 
476     CharString value;
477     SEQAN_ASSERT(getOptionValue(value, parser, "string"));
478     SEQAN_ASSERT_EQ(value, "this-is-a-string-value");
479 }
480 
SEQAN_DEFINE_TEST(test_string_missing_argument)481 SEQAN_DEFINE_TEST(test_string_missing_argument)
482 {
483 
484     ArgumentParser parser;
485     setupStringParser(parser);
486 
487     int argc = 2;
488     const char * argv[2] = {A_STRING_0, A_STRING_2};
489 
490     std::stringstream error_stream;
491     std::stringstream outputStream;
492 
493     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
494     SEQAN_ASSERT_EQ(error_stream.str(), "test: option requires an argument -- string\n");
495     SEQAN_ASSERT_EQ(outputStream.str(), "");
496 }
497 
SEQAN_DEFINE_TEST(test_string_list)498 SEQAN_DEFINE_TEST(test_string_list)
499 {
500     ArgumentParser parser;
501     setupStringParser(parser);
502 
503     int argc = 7;
504     const char * argv[7] = {A_STRING_0, A_STRING_1, A_STRING_3, A_STRING_2, A_STRING_3, A_STRING_1, A_STRING_3};
505 
506     std::stringstream error_stream;
507     std::stringstream outputStream;
508 
509     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
510     SEQAN_ASSERT_EQ(error_stream.str(), "");
511     SEQAN_ASSERT_EQ(outputStream.str(), "");
512 
513     std::vector<std::string> const & values = getOptionValues(parser, "string");
514 
515     SEQAN_ASSERT_EQ(length(values), 3u);
516 
517     for (unsigned i = 0; i < length(values); ++i)
518     {
519         SEQAN_ASSERT_EQ(value(values, i), "this-is-a-string-value");
520     }
521 }
522 
SEQAN_DEFINE_TEST(test_min_max_double_values_in_range)523 SEQAN_DEFINE_TEST(test_min_max_double_values_in_range)
524 {
525     ArgumentParser parser;
526     setupDoubleParser(parser);
527 
528     setMinValue(parser, "double", "1.0");
529     setMaxValue(parser, "double", "2.0");
530 
531     int argc = 3;
532     const char * argv[3] = {A_DOUBLE_0, A_DOUBLE_2, A_DOUBLE_3};
533 
534     std::stringstream error_stream;
535     std::stringstream outputStream;
536 
537     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
538     SEQAN_ASSERT_EQ(outputStream.str(), "");
539 
540     double doubleValue = 0.0;
541     SEQAN_ASSERT(getOptionValue(doubleValue, parser, "double"));
542     SEQAN_ASSERT_EQ(doubleValue, 1.56);
543 }
544 
SEQAN_DEFINE_TEST(test_min_max_double_values_to_small)545 SEQAN_DEFINE_TEST(test_min_max_double_values_to_small)
546 {
547     ArgumentParser parser;
548     setupDoubleParser(parser);
549 
550     setMinValue(parser, "double", "1.6");
551 
552     int argc = 3;
553     const char * argv[3] = {A_DOUBLE_0, A_DOUBLE_2, A_DOUBLE_3};
554 
555     std::stringstream error_stream;
556     std::stringstream outputStream;
557 
558     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
559     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value '1.56' is not in the interval [1.6:+inf]\n");
560     SEQAN_ASSERT_EQ(outputStream.str(), "");
561 }
562 
SEQAN_DEFINE_TEST(test_min_max_double_values_to_big)563 SEQAN_DEFINE_TEST(test_min_max_double_values_to_big)
564 {
565     ArgumentParser parser;
566     setupDoubleParser(parser);
567 
568     setMaxValue(parser, "double", "1.5");
569 
570     int argc = 3;
571     const char * argv[3] = {A_DOUBLE_0, A_DOUBLE_2, A_DOUBLE_3};
572 
573     std::stringstream error_stream;
574     std::stringstream outputStream;
575 
576     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
577     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value '1.56' is not in the interval [-inf:1.5]\n");
578     SEQAN_ASSERT_EQ(outputStream.str(), "");
579 }
580 
SEQAN_DEFINE_TEST(test_min_max_int_values_in_range)581 SEQAN_DEFINE_TEST(test_min_max_int_values_in_range)
582 {
583     ArgumentParser parser;
584     setupIntegerParser(parser);
585 
586     setMinValue(parser, "integer", "-10");
587     setMaxValue(parser, "integer", "2");
588 
589     int argc = 3;
590     const char * argv[3] = {A_INT_0, A_INT_2, A_INT_3};
591 
592     std::stringstream error_stream;
593     std::stringstream outputStream;
594 
595     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
596     SEQAN_ASSERT_EQ(error_stream.str(), "");
597     SEQAN_ASSERT_EQ(outputStream.str(), "");
598 
599     int integerValue = 0;
600     SEQAN_ASSERT(getOptionValue(integerValue, parser, "integer"));
601     SEQAN_ASSERT_EQ(integerValue, 1);
602 }
603 
SEQAN_DEFINE_TEST(test_min_max_int_values_to_small)604 SEQAN_DEFINE_TEST(test_min_max_int_values_to_small)
605 {
606     ArgumentParser parser;
607     setupIntegerParser(parser);
608 
609     setMinValue(parser, "integer", "3");
610 
611     int argc = 3;
612     const char * argv[3] = {A_INT_0, A_INT_2, A_INT_3};
613 
614     std::stringstream error_stream;
615     std::stringstream outputStream;
616 
617     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
618     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value '1' is not in the interval [3:+inf]\n");
619     SEQAN_ASSERT_EQ(outputStream.str(), "");
620 }
621 
SEQAN_DEFINE_TEST(test_min_max_int_values_to_big)622 SEQAN_DEFINE_TEST(test_min_max_int_values_to_big)
623 {
624     ArgumentParser parser;
625     setupIntegerParser(parser);
626 
627     setMaxValue(parser, "integer", "-3");
628 
629     int argc = 3;
630     const char * argv[3] = {A_INT_0, A_INT_2, A_INT_3};
631 
632     std::stringstream error_stream;
633     std::stringstream outputStream;
634 
635     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
636     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value '1' is not in the interval [-inf:-3]\n");
637     SEQAN_ASSERT_EQ(outputStream.str(), "");
638 }
639 
SEQAN_DEFINE_TEST(test_allowed_values_contained)640 SEQAN_DEFINE_TEST(test_allowed_values_contained)
641 {
642     ArgumentParser parser;
643     setupStringParser(parser);
644 
645     setValidValues(parser, "string", "a b c this-is-a-string-value");
646 
647     int argc = 3;
648     const char * argv[3] = {A_STRING_0, A_STRING_2, A_STRING_3};
649 
650     std::stringstream error_stream;
651     std::stringstream outputStream;
652 
653     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
654     SEQAN_ASSERT_EQ(error_stream.str(), "");
655     SEQAN_ASSERT_EQ(outputStream.str(), "");
656 
657     CharString value;
658     SEQAN_ASSERT(getOptionValue(value, parser, "string"));
659     SEQAN_ASSERT_EQ(value, "this-is-a-string-value");
660 }
661 
SEQAN_DEFINE_TEST(test_allowed_values_not_contained)662 SEQAN_DEFINE_TEST(test_allowed_values_not_contained)
663 {
664     ArgumentParser parser;
665     setupStringParser(parser);
666 
667     setValidValues(parser, "string", "a b c");
668 
669     int argc = 3;
670     const char * argv[3] = {A_STRING_0, A_STRING_2, A_STRING_3};
671 
672     std::stringstream error_stream;
673     std::stringstream outputStream;
674 
675     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
676     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value 'this-is-a-string-value' is not in the list of allowed values [a, b, c]\n");
677     SEQAN_ASSERT_EQ(outputStream.str(), "");
678 }
679 
SEQAN_DEFINE_TEST(test_input_file_short)680 SEQAN_DEFINE_TEST(test_input_file_short)
681 {
682     ArgumentParser parser;
683     setupInputFileParser(parser);
684 
685     int argc = 3;
686     const char * argv[3] = {A_IN_FILE_0, A_IN_FILE_1, A_IN_FILE_3};
687 
688     std::stringstream error_stream;
689     std::stringstream outputStream;
690 
691     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
692     SEQAN_ASSERT_EQ(error_stream.str(), "");
693     SEQAN_ASSERT_EQ(outputStream.str(), "");
694 
695     CharString value;
696     SEQAN_ASSERT(getOptionValue(value, parser, "in"));
697     SEQAN_ASSERT_EQ(value, "input.fasta");
698 }
699 
SEQAN_DEFINE_TEST(test_input_file_long)700 SEQAN_DEFINE_TEST(test_input_file_long)
701 {
702     ArgumentParser parser;
703     setupInputFileParser(parser);
704 
705     int argc = 3;
706     const char * argv[3] = {A_IN_FILE_0, A_IN_FILE_2, A_IN_FILE_3};
707 
708     std::stringstream error_stream;
709     std::stringstream outputStream;
710 
711     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
712     SEQAN_ASSERT_EQ(error_stream.str(), "");
713     SEQAN_ASSERT_EQ(outputStream.str(), "");
714 
715     CharString value;
716     SEQAN_ASSERT(getOptionValue(value, parser, "in"));
717     SEQAN_ASSERT_EQ(value, "input.fasta");
718 }
719 
SEQAN_DEFINE_TEST(test_input_file_missing)720 SEQAN_DEFINE_TEST(test_input_file_missing)
721 {
722     ArgumentParser parser;
723     setupInputFileParser(parser);
724 
725     int argc = 2;
726     const char * argv[2] = {A_IN_FILE_0, A_IN_FILE_1};
727 
728     std::stringstream error_stream;
729     std::stringstream outputStream;
730 
731     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
732     SEQAN_ASSERT_EQ(error_stream.str(), "test: option requires an argument -- i\n");
733     SEQAN_ASSERT_EQ(outputStream.str(), "");
734 }
735 
SEQAN_DEFINE_TEST(test_input_file_invalid_type)736 SEQAN_DEFINE_TEST(test_input_file_invalid_type)
737 {
738     ArgumentParser parser;
739     setupInputFileParser(parser);
740 
741     setValidValues(parser, "in", ".fa");
742 
743     int argc = 3;
744     const char * argv[3] = {A_IN_FILE_0, A_IN_FILE_2, A_IN_FILE_3};
745 
746     std::stringstream error_stream;
747     std::stringstream outputStream;
748 
749     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
750     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given path 'input.fasta' does not have one of the valid file extensions [*.fa]\n");
751     SEQAN_ASSERT_EQ(outputStream.str(), "");
752 }
753 
SEQAN_DEFINE_TEST(test_input_file_valid_type)754 SEQAN_DEFINE_TEST(test_input_file_valid_type)
755 {
756     ArgumentParser parser;
757     setupInputFileParser(parser);
758 
759     setValidValues(parser, "in", ".fasta .FASTA .fa");
760 
761     int argc = 3;
762     const char * argv[3] = {A_IN_FILE_0, A_IN_FILE_2, A_IN_FILE_3};
763 
764     std::stringstream error_stream;
765     std::stringstream outputStream;
766 
767     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
768     SEQAN_ASSERT_EQ(error_stream.str(), "");
769     SEQAN_ASSERT_EQ(outputStream.str(), "");
770 
771     CharString value;
772     SEQAN_ASSERT(getOptionValue(value, parser, "in"));
773     SEQAN_ASSERT_EQ(value, "input.fasta");
774 }
775 
SEQAN_DEFINE_TEST(test_input_file_extension)776 SEQAN_DEFINE_TEST(test_input_file_extension)
777 {
778     ArgumentParser parser;
779     setupInputFileParser(parser);
780 
781     setValidValues(parser, "in", ".fasta .FASTA .fa");
782 
783     int argc = 3;
784     const char * argv[3] = {A_IN_FILE_0, A_IN_FILE_2, A_IN_FILE_3};
785 
786     std::stringstream error_stream;
787     std::stringstream outputStream;
788 
789     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
790     SEQAN_ASSERT_EQ(error_stream.str(), "");
791     SEQAN_ASSERT_EQ(outputStream.str(), "");
792 
793     std::string value;
794     value = getOptionFileExtension(parser, "in");
795     SEQAN_ASSERT_EQ(value, ".fasta");
796 }
797 
798 // Test that an automatic --${OPTION}-file-ext option is added with the same list flag and number of values.
SEQAN_DEFINE_TEST(test_input_file_auto_file_ext_option)799 SEQAN_DEFINE_TEST(test_input_file_auto_file_ext_option)
800 {
801     std::vector<std::string> expectedValidValues;
802     expectedValidValues.push_back("fa");
803     expectedValidValues.push_back("TXT");
804 
805     // No list, one value.
806     {
807         ArgumentParser parser;
808 
809         addOption(parser, ArgParseOption("short", "long", "help text", ArgParseOption::INPUT_FILE));
810         setValidValues(parser, "long", ".fa .TXT");
811 
812         SEQAN_ASSERT_NOT(hasOption(parser, "short-file-ext"));
813         SEQAN_ASSERT(hasOption(parser, "long-file-ext"));
814 
815         ArgParseOption & option = getOption(parser, "long-file-ext");
816         SEQAN_ASSERT(isStringArgument(option));
817         SEQAN_ASSERT_NOT(isListArgument(option));
818         SEQAN_ASSERT_EQ(numberOfAllowedValues(option), 1u);
819         SEQAN_ASSERT(option.validValues == expectedValidValues);
820     }
821 
822     // No list, two values.
823     {
824         ArgumentParser parser;
825 
826         addOption(parser, ArgParseOption("short", "long", "help text", ArgParseOption::INPUT_FILE,
827                                          "label", false, 2));
828         setValidValues(parser, "long", ".fa .TXT");
829 
830         SEQAN_ASSERT_NOT(hasOption(parser, "short-file-ext"));
831         SEQAN_ASSERT(hasOption(parser, "long-file-ext"));
832 
833         ArgParseOption & option = getOption(parser, "long-file-ext");
834         SEQAN_ASSERT(isStringArgument(option));
835         SEQAN_ASSERT_NOT(isListArgument(option));
836         SEQAN_ASSERT_EQ(numberOfAllowedValues(option), 2u);
837         SEQAN_ASSERT(option.validValues == expectedValidValues);
838     }
839 
840     // List.
841     {
842         ArgumentParser parser;
843 
844         addOption(parser, ArgParseOption("short", "long", "help text", ArgParseOption::INPUT_FILE,
845                                          "label", true));
846         setValidValues(parser, "long", ".fa .TXT");
847 
848         SEQAN_ASSERT_NOT(hasOption(parser, "short-file-ext"));
849         SEQAN_ASSERT(hasOption(parser, "long-file-ext"));
850 
851         ArgParseOption & option = getOption(parser, "long-file-ext");
852         SEQAN_ASSERT(isStringArgument(option));
853         SEQAN_ASSERT(isListArgument(option));
854         SEQAN_ASSERT_EQ(numberOfAllowedValues(option), 1u);
855         SEQAN_ASSERT(option.validValues == expectedValidValues);
856     }
857 }
858 
SEQAN_DEFINE_TEST(test_output_file_short)859 SEQAN_DEFINE_TEST(test_output_file_short)
860 {
861     ArgumentParser parser;
862     setupOutputFileParser(parser);
863 
864     int argc = 3;
865     const char * argv[3] = {A_OUT_FILE_0, A_OUT_FILE_1, A_OUT_FILE_3};
866 
867     std::stringstream error_stream;
868     std::stringstream outputStream;
869 
870     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
871     SEQAN_ASSERT_EQ(error_stream.str(), "");
872     SEQAN_ASSERT_EQ(outputStream.str(), "");
873 
874     CharString value;
875     SEQAN_ASSERT(getOptionValue(value, parser, "out"));
876     SEQAN_ASSERT_EQ(value, "output.fasta");
877 }
878 
SEQAN_DEFINE_TEST(test_output_file_long)879 SEQAN_DEFINE_TEST(test_output_file_long)
880 {
881     ArgumentParser parser;
882     setupOutputFileParser(parser);
883 
884     int argc = 3;
885     const char * argv[3] = {A_OUT_FILE_0, A_OUT_FILE_2, A_OUT_FILE_3};
886 
887     std::stringstream error_stream;
888     std::stringstream outputStream;
889 
890     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
891     SEQAN_ASSERT_EQ(error_stream.str(), "");
892     SEQAN_ASSERT_EQ(outputStream.str(), "");
893 
894     CharString value;
895     SEQAN_ASSERT(getOptionValue(value, parser, "out"));
896     SEQAN_ASSERT_EQ(value, "output.fasta");
897 }
898 
SEQAN_DEFINE_TEST(test_output_file_missing)899 SEQAN_DEFINE_TEST(test_output_file_missing)
900 {
901     ArgumentParser parser;
902     setupOutputFileParser(parser);
903 
904     int argc = 2;
905     const char * argv[2] = {A_OUT_FILE_0, A_OUT_FILE_1};
906 
907     std::stringstream error_stream;
908     std::stringstream outputStream;
909 
910     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
911     SEQAN_ASSERT_EQ(error_stream.str(), "test: option requires an argument -- o\n");
912     SEQAN_ASSERT_EQ(outputStream.str(), "");
913 }
914 
SEQAN_DEFINE_TEST(test_output_file_invalid_type)915 SEQAN_DEFINE_TEST(test_output_file_invalid_type)
916 {
917     ArgumentParser parser;
918     setupOutputFileParser(parser);
919 
920     setValidValues(parser, "out", ".fa");
921 
922     int argc = 3;
923     const char * argv[3] = {A_OUT_FILE_0, A_OUT_FILE_2, A_OUT_FILE_3};
924 
925     std::stringstream error_stream;
926     std::stringstream outputStream;
927 
928     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
929     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given path 'output.fasta' does not have one of the valid file extensions [*.fa]\n");
930     SEQAN_ASSERT_EQ(outputStream.str(), "");
931 }
932 
SEQAN_DEFINE_TEST(test_output_file_valid_type)933 SEQAN_DEFINE_TEST(test_output_file_valid_type)
934 {
935     ArgumentParser parser;
936     setupOutputFileParser(parser);
937 
938     setValidValues(parser, "out", ".fasta .FASTA .fa");
939 
940     int argc = 3;
941     const char * argv[3] = {A_OUT_FILE_0, A_OUT_FILE_2, A_OUT_FILE_3};
942 
943     std::stringstream error_stream;
944     std::stringstream outputStream;
945 
946     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
947     SEQAN_ASSERT_EQ(error_stream.str(), "");
948     SEQAN_ASSERT_EQ(outputStream.str(), "");
949 
950     CharString value;
951     SEQAN_ASSERT(getOptionValue(value, parser, "out"));
952     SEQAN_ASSERT_EQ(value, "output.fasta");
953 }
954 
SEQAN_DEFINE_TEST(test_output_file_extension)955 SEQAN_DEFINE_TEST(test_output_file_extension)
956 {
957     ArgumentParser parser;
958     setupOutputFileParser(parser);
959 
960     setValidValues(parser, "out", ".fasta .FASTA .fa");
961 
962     int argc = 3;
963     const char * argv[3] = {A_OUT_FILE_0, A_OUT_FILE_2, A_OUT_FILE_3};
964 
965     std::stringstream error_stream;
966     std::stringstream outputStream;
967 
968     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
969     SEQAN_ASSERT_EQ(error_stream.str(), "");
970     SEQAN_ASSERT_EQ(outputStream.str(), "");
971 
972     CharString value;
973     value = getOptionFileExtension(parser, "out");
974     SEQAN_ASSERT_EQ(value, ".fasta");
975 }
976 
SEQAN_DEFINE_TEST(test_output_file_extension_targz)977 SEQAN_DEFINE_TEST(test_output_file_extension_targz)
978 {
979     ArgumentParser parser;
980     setupOutputFileParser(parser);
981 
982     setValidValues(parser, "out", ".tar.gz .tar");
983 
984     int argc = 3;
985     const char * argv[3] = {A_OUT_FILE_0, A_OUT_FILE_2, A_OUT_FILE_4};
986 
987     std::stringstream error_stream;
988     std::stringstream outputStream;
989 
990     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
991     SEQAN_ASSERT_EQ(error_stream.str(), "");
992     SEQAN_ASSERT_EQ(outputStream.str(), "");
993 
994     CharString value;
995     value = getOptionFileExtension(parser, "out");
996     SEQAN_ASSERT_EQ(value, ".tar.gz");
997 }
998 
999 // Value with invalid extension given on command line but overridden with valid extension.
SEQAN_DEFINE_TEST(test_output_file_explicit_extension_valid)1000 SEQAN_DEFINE_TEST(test_output_file_explicit_extension_valid)
1001 {
1002     ArgumentParser parser;
1003     setupOutputFileParser(parser);
1004 
1005     setValidValues(parser, "out", ".fasta .FASTA .fa");
1006 
1007     int argc = 5;
1008     const char * argv[5] = {A_OUT_FILE_0, A_OUT_FILE_2, A_OUT_FILE_5, A_OUT_FILE_6, A_OUT_FILE_7};
1009 
1010     std::stringstream error_stream;
1011     std::stringstream outputStream;
1012 
1013     SEQAN_ASSERT_EQ(parse(parser, argc, argv, std::cerr, std::cerr), ArgumentParser::PARSE_OK);
1014     SEQAN_ASSERT_EQ(error_stream.str(), "");
1015     SEQAN_ASSERT_EQ(outputStream.str(), "");
1016 
1017     CharString value;
1018     value = getOptionFileExtension(parser, "out");
1019     SEQAN_ASSERT_EQ(value, ".fasta");
1020 }
1021 
1022 // Value with valid extension given on command line but overridden with invalid extension.
SEQAN_DEFINE_TEST(test_output_file_explicit_extension_invalid)1023 SEQAN_DEFINE_TEST(test_output_file_explicit_extension_invalid)
1024 {
1025     ArgumentParser parser;
1026     setupOutputFileParser(parser);
1027 
1028     setValidValues(parser, "out", ".fasta .FASTA .fa");
1029 
1030     int argc = 5;
1031     const char * argv[5] = {A_OUT_FILE_0, A_OUT_FILE_2, A_OUT_FILE_3, A_OUT_FILE_6, A_OUT_FILE_8};
1032 
1033     std::stringstream error_stream;
1034     std::stringstream outputStream;
1035 
1036     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
1037     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given path 'output.fasta' does not have one of the valid file extensions [*.fasta, *.FASTA, *.fa]; the file extension was overridden to be '.txt'\n");
1038     SEQAN_ASSERT_EQ(outputStream.str(), "");
1039 }
1040 
SEQAN_DEFINE_TEST(test_argument_string)1041 SEQAN_DEFINE_TEST(test_argument_string)
1042 {
1043     ArgumentParser parser;
1044     addArgument(parser, ArgParseArgument(ArgParseArgument::STRING));
1045     addArgument(parser, ArgParseArgument(ArgParseArgument::STRING));
1046 
1047     int argc = 3;
1048     const char * argv[3] = {A_ARGUMENT_0, A_ARGUMENT_1, A_ARGUMENT_2};
1049 
1050     std::stringstream error_stream;
1051     std::stringstream outputStream;
1052 
1053     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
1054     SEQAN_ASSERT_EQ(error_stream.str(), "");
1055     SEQAN_ASSERT_EQ(outputStream.str(), "");
1056 }
1057 
SEQAN_DEFINE_TEST(test_argument_not_all_set)1058 SEQAN_DEFINE_TEST(test_argument_not_all_set)
1059 {
1060     ArgumentParser parser;
1061     addArgument(parser, ArgParseArgument(ArgParseArgument::STRING));
1062     addArgument(parser, ArgParseArgument(ArgParseArgument::STRING));
1063 
1064     int argc = 2;
1065     const char * argv[2] = {A_ARGUMENT_0, A_ARGUMENT_1};
1066 
1067     std::stringstream error_stream;
1068     std::stringstream outputStream;
1069 
1070     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
1071     SEQAN_ASSERT_EQ(error_stream.str(), "test: Not enough arguments were provided.\nTry 'test --help' for more information.\n");
1072     SEQAN_ASSERT_EQ(outputStream.str(), "");
1073 }
1074 
SEQAN_DEFINE_TEST(test_argument_double)1075 SEQAN_DEFINE_TEST(test_argument_double)
1076 {
1077     ArgumentParser parser;
1078     addArgument(parser, ArgParseArgument(ArgParseArgument::DOUBLE));
1079 
1080     int argc = 2;
1081     const char * argv[2] = {A_ARGUMENT_0, A_ARGUMENT_DOUBLE_5};
1082 
1083     std::stringstream error_stream;
1084     std::stringstream outputStream;
1085 
1086     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
1087     SEQAN_ASSERT_EQ(error_stream.str(), "");
1088     SEQAN_ASSERT_EQ(outputStream.str(), "");
1089 
1090     double doubleValue = 0.0;
1091     SEQAN_ASSERT(getArgumentValue(doubleValue, parser, 0));
1092     SEQAN_ASSERT_EQ(doubleValue, 6.0221418e23);
1093 }
1094 
SEQAN_DEFINE_TEST(test_argument_not_a_double)1095 SEQAN_DEFINE_TEST(test_argument_not_a_double)
1096 {
1097     ArgumentParser parser;
1098     addArgument(parser, ArgParseArgument(ArgParseArgument::DOUBLE));
1099 
1100     int argc = 2;
1101     const char * argv[2] = {A_ARGUMENT_0, A_ARGUMENT_1};
1102 
1103     std::stringstream error_stream;
1104     std::stringstream outputStream;
1105 
1106     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
1107     SEQAN_ASSERT_EQ(error_stream.str(), "test: the given value 'argument1' cannot be casted to double\n");
1108     SEQAN_ASSERT_EQ(outputStream.str(), "");
1109 }
1110 
SEQAN_DEFINE_TEST(test_argument_auto_file_ext_option)1111 SEQAN_DEFINE_TEST(test_argument_auto_file_ext_option)
1112 {
1113     std::vector<std::string> expectedValidValues;
1114     expectedValidValues.push_back("fa");
1115     expectedValidValues.push_back("TXT");
1116 
1117     // No list, one value.
1118     {
1119         ArgumentParser parser;
1120         addArgument(parser, ArgParseArgument(ArgParseArgument::INPUT_FILE));
1121         setValidValues(parser, 0, "fa TXT");
1122 
1123         SEQAN_ASSERT(hasOption(parser, "arg-1-file-ext"));
1124 
1125         ArgParseOption & option = getOption(parser, "arg-1-file-ext");
1126         SEQAN_ASSERT(isStringArgument(option));
1127         SEQAN_ASSERT_NOT(isListArgument(option));
1128         SEQAN_ASSERT_EQ(numberOfAllowedValues(option), 1u);
1129         SEQAN_ASSERT(option.validValues == expectedValidValues);
1130     }
1131 
1132     // NB: tuple arguments unsupported
1133 
1134     // List, one value.
1135     {
1136         ArgumentParser parser;
1137         addArgument(parser, ArgParseArgument(ArgParseArgument::INPUT_FILE, "LABEL", true));
1138         setValidValues(parser, 0, "fa TXT");
1139 
1140         SEQAN_ASSERT(hasOption(parser, "arg-1-file-ext"));
1141 
1142         ArgParseOption & option = getOption(parser, "arg-1-file-ext");
1143         SEQAN_ASSERT(isStringArgument(option));
1144         SEQAN_ASSERT(isListArgument(option));
1145         SEQAN_ASSERT_EQ(numberOfAllowedValues(option), 1u);
1146         SEQAN_ASSERT(option.validValues == expectedValidValues);
1147     }
1148 
1149     // Second argument, just to make sure.
1150     {
1151         ArgumentParser parser;
1152         addArgument(parser, ArgParseArgument(ArgParseArgument::DOUBLE));
1153         addArgument(parser, ArgParseArgument(ArgParseArgument::INPUT_FILE));
1154         setValidValues(parser, 1, "fa TXT");
1155 
1156         SEQAN_ASSERT(hasOption(parser, "arg-2-file-ext"));
1157 
1158         ArgParseOption & option = getOption(parser, "arg-2-file-ext");
1159 
1160         SEQAN_ASSERT(isStringArgument(option));
1161         SEQAN_ASSERT_NOT(isListArgument(option));
1162         SEQAN_ASSERT_EQ(numberOfAllowedValues(option), 1u);
1163         SEQAN_ASSERT(option.validValues == expectedValidValues);
1164     }
1165 }
1166 
SEQAN_DEFINE_TEST(test_isDouble)1167 SEQAN_DEFINE_TEST(test_isDouble)
1168 {
1169     CharString a = "this is not a double";
1170     CharString b = "2.5";
1171     CharString c = "-45.5245";
1172     CharString d = "6.0221418e23";
1173     CharString e = "-45.5245aeeeb";
1174 
1175     SEQAN_ASSERT(!_isDouble(a));
1176     SEQAN_ASSERT(_isDouble(b));
1177     SEQAN_ASSERT(_isDouble(c));
1178     SEQAN_ASSERT(_isDouble(d));
1179     SEQAN_ASSERT(!_isDouble(e));
1180 }
1181 
SEQAN_DEFINE_TEST(test_isInt)1182 SEQAN_DEFINE_TEST(test_isInt)
1183 {
1184     CharString a = "this is not an int";
1185     CharString b = "2";
1186     CharString c = "-4253252";
1187     CharString d = "6aaefgeag";
1188 
1189     SEQAN_ASSERT(!_isInt(a));
1190     SEQAN_ASSERT(_isInt(b));
1191     SEQAN_ASSERT(_isInt(c));
1192     SEQAN_ASSERT(!_isInt(d));
1193 }
1194 
1195 // Testing lists of tuples
SEQAN_DEFINE_TEST(test_int_list_option)1196 SEQAN_DEFINE_TEST(test_int_list_option)
1197 {
1198     ArgumentParser parser;
1199     addOption(parser, ArgParseOption("l", "list", "this is a list option", ArgParseArgument::INTEGER, "", true, 2));
1200 
1201     int argc = 7;
1202     const char * argv[7] = {A_TUPLE_LIST, A_TUPLE_LIST_L, A_TUPLE_LIST_L_1, A_TUPLE_LIST_L_2, A_TUPLE_LIST_L, A_TUPLE_LIST_L_3, A_TUPLE_LIST_L_4};
1203 
1204     std::stringstream error_stream;
1205     std::stringstream outputStream;
1206 
1207     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
1208     SEQAN_ASSERT_EQ(error_stream.str(), "");
1209     SEQAN_ASSERT_EQ(outputStream.str(), "");
1210 
1211     SEQAN_ASSERT_EQ(getOptionValueCount(parser, "list"), 4u);
1212 
1213     int value = 0;
1214     SEQAN_ASSERT(getOptionValue(value, parser, "list", 0));
1215     SEQAN_ASSERT_EQ(value, 10);
1216     SEQAN_ASSERT(getOptionValue(value, parser, "list", 1));
1217     SEQAN_ASSERT_EQ(value, 20);
1218 
1219     SEQAN_ASSERT(getOptionValue(value, parser, "list", 2));
1220     SEQAN_ASSERT_EQ(value, 30);
1221     SEQAN_ASSERT(getOptionValue(value, parser, "list", 3));
1222     SEQAN_ASSERT_EQ(value, 40);
1223 }
1224 
SEQAN_DEFINE_TEST(test_double_list_option)1225 SEQAN_DEFINE_TEST(test_double_list_option)
1226 {
1227     ArgumentParser parser;
1228     addOption(parser, ArgParseOption("k", "double-list", "this is a list option", ArgParseArgument::DOUBLE, "", true, 3));
1229 
1230     int argc = 9;
1231     const char * argv[9] = {A_TUPLE_LIST, A_TUPLE_LIST_DL, A_TUPLE_LIST_DL_1, A_TUPLE_LIST_DL_2, A_TUPLE_LIST_DL_3, A_TUPLE_LIST_DL, A_TUPLE_LIST_DL_4, A_TUPLE_LIST_DL_5, A_TUPLE_LIST_DL_6};
1232 
1233     std::stringstream error_stream;
1234     std::stringstream outputStream;
1235 
1236     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
1237     SEQAN_ASSERT_EQ(error_stream.str(), "");
1238     SEQAN_ASSERT_EQ(outputStream.str(), "");
1239 
1240     SEQAN_ASSERT_EQ(getOptionValueCount(parser, "double-list"), 6u);
1241 
1242     double value = 0;
1243     SEQAN_ASSERT(getOptionValue(value, parser, "double-list", 0));
1244     SEQAN_ASSERT_EQ(value, 5.1);
1245     SEQAN_ASSERT(getOptionValue(value, parser, "double-list", 1));
1246     SEQAN_ASSERT_EQ(value, 6.2);
1247     SEQAN_ASSERT(getOptionValue(value, parser, "double-list", 2));
1248     SEQAN_ASSERT_EQ(value, 7.3);
1249 
1250     SEQAN_ASSERT(getOptionValue(value, parser, "double-list", 3));
1251     SEQAN_ASSERT_EQ(value, 5.5);
1252     SEQAN_ASSERT(getOptionValue(value, parser, "double-list", 4));
1253     SEQAN_ASSERT_EQ(value, 6.6);
1254     SEQAN_ASSERT(getOptionValue(value, parser, "double-list", 5));
1255     SEQAN_ASSERT_EQ(value, 7.7);
1256 
1257 }
1258 
SEQAN_DEFINE_TEST(test_double_list_option_not_enough_arguments)1259 SEQAN_DEFINE_TEST(test_double_list_option_not_enough_arguments)
1260 {
1261     ArgumentParser parser;
1262     addOption(parser, ArgParseOption("k", "double-list", "this is a list option", ArgParseArgument::DOUBLE, "", true, 3));
1263 
1264     int argc = 8;
1265     const char * argv[8] = {A_TUPLE_LIST, A_TUPLE_LIST_DL, A_TUPLE_LIST_DL_1, A_TUPLE_LIST_DL_2, A_TUPLE_LIST_DL_3, A_TUPLE_LIST_DL, A_TUPLE_LIST_DL_4, A_TUPLE_LIST_DL_5};
1266 
1267     std::stringstream error_stream;
1268     std::stringstream outputStream;
1269 
1270     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_ERROR);
1271     SEQAN_ASSERT_EQ(error_stream.str(), "test_tuple_list: option requires an argument -- k\n");
1272     SEQAN_ASSERT_EQ(outputStream.str(), "");
1273 }
1274 
setUpBoolParser(ArgumentParser & parser)1275 void setUpBoolParser(ArgumentParser & parser)
1276 {
1277     addOption(parser, ArgParseOption("b", "", "This is a boolean flag"));
1278     addOption(parser, ArgParseOption("c", "", "This is a boolean flag"));
1279     addOption(parser, ArgParseOption("d", "", "This is a boolean flag that we will not set."));
1280 }
1281 
SEQAN_DEFINE_TEST(test_boolean_flags)1282 SEQAN_DEFINE_TEST(test_boolean_flags)
1283 {
1284     ArgumentParser parser;
1285     setUpBoolParser(parser);
1286 
1287     int argc = 3;
1288     const char * argv[3] = { A_BOOL, A_BOOL_1, A_BOOL_2 };
1289 
1290     std::stringstream error_stream;
1291     std::stringstream outputStream;
1292 
1293     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
1294     SEQAN_ASSERT_EQ(error_stream.str(), "");
1295     SEQAN_ASSERT_EQ(outputStream.str(), "");
1296 
1297     bool isSet = false;
1298     SEQAN_ASSERT(getOptionValue(isSet, parser, "b"));
1299     SEQAN_ASSERT(isSet);
1300 
1301     isSet = false;
1302     SEQAN_ASSERT(getOptionValue(isSet, parser, "c"));
1303     SEQAN_ASSERT(isSet);
1304 
1305     isSet = true;
1306     SEQAN_ASSERT(getOptionValue(isSet, parser, "d"));
1307     SEQAN_ASSERT(!isSet);
1308 }
1309 
SEQAN_DEFINE_TEST(test_combined_boolean_flags)1310 SEQAN_DEFINE_TEST(test_combined_boolean_flags)
1311 {
1312     ArgumentParser parser;
1313     setUpBoolParser(parser);
1314 
1315     int argc = 2;
1316     const char * argv[2] = { A_BOOL, A_BOOL_3 };
1317 
1318     std::stringstream error_stream;
1319     std::stringstream outputStream;
1320 
1321     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
1322     SEQAN_ASSERT_EQ(error_stream.str(), "");
1323     SEQAN_ASSERT_EQ(outputStream.str(), "");
1324 
1325     bool isSet = false;
1326     SEQAN_ASSERT(getOptionValue(isSet, parser, "b"));
1327     SEQAN_ASSERT(isSet);
1328 
1329     isSet = false;
1330     SEQAN_ASSERT(getOptionValue(isSet, parser, "c"));
1331     SEQAN_ASSERT(isSet);
1332 
1333     isSet = true;
1334     SEQAN_ASSERT(getOptionValue(isSet, parser, "d"));
1335     SEQAN_ASSERT(!isSet);
1336 }
1337 
SEQAN_DEFINE_TEST(test_long_short_flag_name)1338 SEQAN_DEFINE_TEST(test_long_short_flag_name)
1339 {
1340     ArgumentParser parser;
1341     addOption(parser, ArgParseOption("bc", "", "This is a boolean flag"));
1342     addOption(parser, ArgParseOption("d", "", "This is a boolean flag"));
1343 
1344     int argc = 2;
1345     const char * argv[2] = { A_BOOL, A_BOOL_3 };
1346 
1347     std::stringstream error_stream;
1348     std::stringstream outputStream;
1349 
1350     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
1351     SEQAN_ASSERT_EQ(error_stream.str(), "");
1352     SEQAN_ASSERT_EQ(outputStream.str(), "");
1353 
1354     bool isSet = false;
1355     SEQAN_ASSERT(getOptionValue(isSet, parser, "bc"));
1356     SEQAN_ASSERT(isSet);
1357 
1358     isSet = true;
1359     SEQAN_ASSERT(getOptionValue(isSet, parser, "d"));
1360     SEQAN_ASSERT(!isSet);
1361 }
1362 
SEQAN_DEFINE_TEST(test_default_value)1363 SEQAN_DEFINE_TEST(test_default_value)
1364 {
1365     ArgumentParser parser;
1366     setupStringParser(parser);
1367     setDefaultValue(parser, "string", "default-string-value");
1368 
1369     CharString defaultValue;
1370     SEQAN_ASSERT(getOptionValue(defaultValue, parser, "string"));
1371     SEQAN_ASSERT_EQ(defaultValue, "default-string-value");
1372 
1373     int argc = 3;
1374     const char * argv[3] = {A_STRING_0, A_STRING_1, A_STRING_3};
1375 
1376     std::stringstream error_stream;
1377     std::stringstream outputStream;
1378 
1379     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
1380     SEQAN_ASSERT_EQ(error_stream.str(), "");
1381     SEQAN_ASSERT_EQ(outputStream.str(), "");
1382 
1383     CharString value;
1384     SEQAN_ASSERT(getOptionValue(value, parser, "string"));
1385     SEQAN_ASSERT_EQ(value, "this-is-a-string-value");
1386 }
1387 
1388 
SEQAN_DEFINE_TEST(test_parse_non_const_cstring)1389 SEQAN_DEFINE_TEST(test_parse_non_const_cstring)
1390 {
1391     // Call parse() with (char **) and not (char const **) to test that this works as well.
1392     ArgumentParser parser;
1393     setupIntegerParser(parser);
1394     setDefaultValue(parser, "integer", "2");
1395     setMaxValue(parser, "integer", "3");
1396 
1397     int defaultValue;
1398     SEQAN_ASSERT(getOptionValue(defaultValue, parser, "integer"));
1399     SEQAN_ASSERT_EQ(defaultValue, 2);
1400 
1401     char buffer1[100];
1402     strncpy(buffer1, "program_name", 100);
1403     char buffer2[100];
1404     strncpy(buffer2, "-i", 100);
1405     char buffer3[100];
1406     strncpy(buffer3, "1", 100);
1407     int argc = 3;
1408     char * argv[3] = {&buffer1[0], &buffer2[0], &buffer3[0]};
1409 
1410     std::stringstream error_stream;
1411     std::stringstream outputStream;
1412 
1413     SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, std::cout), ArgumentParser::PARSE_OK);
1414     SEQAN_ASSERT_EQ(error_stream.str(), "");
1415     SEQAN_ASSERT_EQ(outputStream.str(), "");
1416 
1417     int value;
1418     SEQAN_ASSERT(getOptionValue(value, parser, "integer"));
1419     SEQAN_ASSERT_EQ(value, 1);
1420 }
1421 
1422 } // namespace seqan
1423 
1424 #endif  // SEQAN_TESTS_ARG_PARSE_TEST_ARG_PARSE_H_
1425