Line data Source code
1 : // Copyright (c) 2006-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/advgetopt
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 : // advgetopt
21 : //
22 : #include <advgetopt/validator_duration.h>
23 : #include <advgetopt/validator_size.h>
24 :
25 : #include <advgetopt/exception.h>
26 :
27 :
28 : // self
29 : //
30 : #include "catch_main.h"
31 :
32 :
33 : // snapdev
34 : //
35 : #include <snapdev/ostream_int128.h>
36 :
37 :
38 : // C++
39 : //
40 : #include <cmath>
41 : #include <fstream>
42 : #include <iomanip>
43 :
44 :
45 : // last include
46 : //
47 : #include <snapdev/poison.h>
48 :
49 :
50 :
51 :
52 :
53 : namespace
54 : {
55 :
56 : struct duration_t
57 : {
58 : char const * const f_suffix = nullptr;
59 : double f_factor = 1.0;
60 : };
61 :
62 : constexpr duration_t const g_duration_suffixes[] =
63 : {
64 : { "", 1.0 },
65 : { "s", 1.0 },
66 : { "second", 1.0 },
67 : { "seconds", 1.0 },
68 :
69 : { "m", -1.0 }, // may represent minutes or months
70 : { "minute", 60.0 },
71 : { "minutes", 60.0 },
72 :
73 : { "h", 3600.0 },
74 : { "hour", 3600.0 },
75 : { "hours", 3600.0 },
76 :
77 : { "d", 86400.0 },
78 : { "day", 86400.0 },
79 : { "days", 86400.0 },
80 :
81 : { "w", 86400.0 * 7.0 },
82 : { "week", 86400.0 * 7.0 },
83 : { "weeks", 86400.0 * 7.0 },
84 :
85 : { "month", 86400.0 * 30.0 },
86 : { "months", 86400.0 * 30.0 },
87 :
88 : { "y", 86400.0 * 365.0 },
89 : { "year", 86400.0 * 365.0 },
90 : { "years", 86400.0 * 365.0 },
91 : };
92 :
93 : struct size_suffix_t
94 : {
95 : char const * const f_suffix = nullptr;
96 : int f_base = 1000.0;
97 : int f_power = 0.0;
98 : };
99 :
100 : constexpr size_suffix_t const g_size_suffixes[] =
101 : {
102 : { "", 1000, 0 },
103 : { "B", 1000, 0 },
104 :
105 : { "kB", 1000, 1 },
106 : { "KiB", 1024, 1 },
107 :
108 : { "MB", 1000, 2 },
109 : { "MiB", 1024, 2 },
110 :
111 : { "GB", 1000, 3 },
112 : { "GiB", 1024, 3 },
113 :
114 : { "TB", 1000, 4 },
115 : { "TiB", 1024, 4 },
116 :
117 : { "PB", 1000, 5 },
118 : { "PiB", 1024, 5 },
119 :
120 : { "EB", 1000, 6 },
121 : { "EiB", 1024, 6 },
122 :
123 : { "ZB", 1000, 7 },
124 : { "ZiB", 1024, 7 },
125 :
126 : { "YB", 1000, 8 },
127 : { "YiB", 1024, 8 },
128 : };
129 :
130 123683 : std::int64_t large_rnd(bool zero_allowed = true)
131 : {
132 : for(;;)
133 : {
134 123683 : std::int64_t const result((static_cast<std::int64_t>(rand()) << 0)
135 123683 : ^ (static_cast<std::int64_t>(rand()) << 16)
136 123683 : ^ (static_cast<std::int64_t>(rand()) << 32)
137 123683 : ^ (static_cast<std::int64_t>(rand()) << 48));
138 123683 : if(result != 0
139 0 : || zero_allowed)
140 : {
141 247366 : return result;
142 : }
143 0 : }
144 : }
145 :
146 : }
147 :
148 :
149 :
150 4 : CATCH_TEST_CASE("unknown_validator", "[validator][valid][validation]")
151 : {
152 4 : CATCH_START_SECTION("Undefined validator")
153 : // this is a valid case, it does not throw, it just returns a nullptr
154 : //
155 1 : CATCH_REQUIRE(advgetopt::validator::create("unknown", advgetopt::string_list_t()) == nullptr);
156 : CATCH_END_SECTION()
157 :
158 4 : CATCH_START_SECTION("Empty string")
159 1 : CATCH_REQUIRE(advgetopt::validator::create(std::string()) == nullptr);
160 : CATCH_END_SECTION()
161 2 : }
162 :
163 :
164 :
165 5 : CATCH_TEST_CASE("email_validator", "[invalid][validation]")
166 : {
167 6 : CATCH_START_SECTION("email_validator: Verify that email verification works.")
168 : {
169 2 : advgetopt::validator::pointer_t email(advgetopt::validator::create("email"));
170 :
171 1 : CATCH_REQUIRE(email != nullptr);
172 1 : CATCH_REQUIRE(email->name() == "email");
173 :
174 1 : CATCH_REQUIRE_FALSE(email->validate(""));
175 1 : CATCH_REQUIRE(email->validate("user@example.com"));
176 1 : CATCH_REQUIRE(email->validate("USER@EXAMPLE.COM"));
177 1 : CATCH_REQUIRE_FALSE(email->validate("user1@example.com, user2@example.com, user3@example.com"));
178 1 : CATCH_REQUIRE_FALSE(email->validate("User!example.com"));
179 1 : CATCH_REQUIRE_FALSE(email->validate("@example.com"));
180 1 : CATCH_REQUIRE_FALSE(email->validate("uSeR@"));
181 1 : CATCH_REQUIRE_FALSE(email->validate("uSeR@com"));
182 : }
183 : CATCH_END_SECTION()
184 :
185 6 : CATCH_START_SECTION("email_validator: Verify that one email verification works (single explicitly).")
186 : {
187 2 : advgetopt::validator::pointer_t email(advgetopt::validator::create("email(single)"));
188 :
189 1 : CATCH_REQUIRE(email != nullptr);
190 1 : CATCH_REQUIRE(email->name() == "email");
191 :
192 1 : CATCH_REQUIRE_FALSE(email->validate(""));
193 1 : CATCH_REQUIRE(email->validate("user@example.com"));
194 1 : CATCH_REQUIRE(email->validate("USER@EXAMPLE.COM"));
195 1 : CATCH_REQUIRE_FALSE(email->validate("user1@example.com, user2@example.com, user3@example.com"));
196 1 : CATCH_REQUIRE_FALSE(email->validate("User!example.com"));
197 1 : CATCH_REQUIRE_FALSE(email->validate("@example.com"));
198 1 : CATCH_REQUIRE_FALSE(email->validate("uSeR@"));
199 1 : CATCH_REQUIRE_FALSE(email->validate("uSeR@com"));
200 : }
201 : CATCH_END_SECTION()
202 :
203 6 : CATCH_START_SECTION("email_validator: Verify that multiple emails verification works.")
204 : {
205 2 : advgetopt::validator::pointer_t email(advgetopt::validator::create("email(multiple)"));
206 :
207 1 : CATCH_REQUIRE(email != nullptr);
208 1 : CATCH_REQUIRE(email->name() == "email");
209 :
210 1 : CATCH_REQUIRE_FALSE(email->validate(""));
211 1 : CATCH_REQUIRE(email->validate("user1@example.com, user2@example.com, user3@example.com"));
212 1 : CATCH_REQUIRE(email->validate("USER@EXAMPLE.COM"));
213 1 : CATCH_REQUIRE_FALSE(email->validate("User!example.com"));
214 1 : CATCH_REQUIRE_FALSE(email->validate("@example.com"));
215 1 : CATCH_REQUIRE_FALSE(email->validate("uSeR@"));
216 1 : CATCH_REQUIRE_FALSE(email->validate("uSeR@com"));
217 : }
218 : CATCH_END_SECTION()
219 3 : }
220 :
221 :
222 :
223 5 : CATCH_TEST_CASE("integer_validator", "[validator][valid][validation]")
224 : {
225 6 : CATCH_START_SECTION("integer_validator: Verify the integer validator")
226 : {
227 2 : advgetopt::validator::pointer_t integer_validator(advgetopt::validator::create("integer", advgetopt::string_list_t()));
228 :
229 1 : CATCH_REQUIRE(integer_validator != nullptr);
230 1 : CATCH_REQUIRE(integer_validator->name() == "integer");
231 :
232 1 : CATCH_REQUIRE_FALSE(integer_validator->validate(""));
233 1 : CATCH_REQUIRE_FALSE(integer_validator->validate("+"));
234 1 : CATCH_REQUIRE_FALSE(integer_validator->validate("-"));
235 :
236 1001 : for(int idx(0); idx < 1000; ++idx)
237 : {
238 1000 : std::int64_t value(large_rnd());
239 2000 : std::string const v(std::to_string(value));
240 :
241 1000 : CATCH_REQUIRE(integer_validator->validate(v));
242 :
243 1000 : if(value >= 0)
244 : {
245 520 : CATCH_REQUIRE(integer_validator->validate('+' + v));
246 : }
247 :
248 2000 : std::string const space_before(' ' + v);
249 1000 : CATCH_REQUIRE_FALSE(integer_validator->validate(space_before));
250 :
251 2000 : std::string const space_after(v + ' ');
252 1000 : CATCH_REQUIRE_FALSE(integer_validator->validate(space_after));
253 :
254 2000 : std::string const before(static_cast<char>(rand() % 26 + 'a') + v);
255 1000 : CATCH_REQUIRE_FALSE(integer_validator->validate(before));
256 :
257 2000 : std::string const after(v + static_cast<char>(rand() % 26 + 'a'));
258 1000 : CATCH_REQUIRE_FALSE(integer_validator->validate(after));
259 : }
260 :
261 : // max number
262 1 : CATCH_REQUIRE(integer_validator->validate("9223372036854775807"));
263 1 : CATCH_REQUIRE(integer_validator->validate("+9223372036854775807"));
264 :
265 : // overflow
266 1 : CATCH_REQUIRE_FALSE(integer_validator->validate("9223372036854775808"));
267 1 : CATCH_REQUIRE_FALSE(integer_validator->validate("+9223372036854775808"));
268 :
269 : // min number
270 1 : CATCH_REQUIRE(integer_validator->validate("-9223372036854775808"));
271 :
272 : // underflow
273 1 : CATCH_REQUIRE_FALSE(integer_validator->validate("-9223372036854775809"));
274 :
275 : // too many digits
276 1 : CATCH_REQUIRE_FALSE(integer_validator->validate("92233720368547758091"));
277 1 : CATCH_REQUIRE_FALSE(integer_validator->validate("+92233720368547758092"));
278 1 : CATCH_REQUIRE_FALSE(integer_validator->validate("-92233720368547758093"));
279 : }
280 : CATCH_END_SECTION()
281 :
282 6 : CATCH_START_SECTION("integer_validator: Verify the integer ranges")
283 : {
284 1 : bool had_standalone(false);
285 21 : for(int count(0); count < 20 || !had_standalone; ++count)
286 : {
287 20 : std::int64_t min(large_rnd());
288 20 : std::int64_t max(large_rnd());
289 20 : if(min > max)
290 : {
291 11 : std::swap(min, max);
292 : }
293 :
294 40 : std::string const & smin(std::to_string(min));
295 40 : std::string const & smax(std::to_string(max));
296 :
297 40 : std::string range("...");
298 80 : for(int three(0); three < 3; ++three)
299 : {
300 60 : if(rand() % 5 == 0)
301 : {
302 15 : range = ' ' + range;
303 : }
304 60 : if(rand() % 5 == 0)
305 : {
306 10 : range = range + ' ';
307 : }
308 : }
309 20 : range = smin + range + smax;
310 80 : for(int three(0); three < 3; ++three)
311 : {
312 60 : if(rand() % 5 == 0)
313 : {
314 13 : range = ' ' + range;
315 : }
316 60 : if(rand() % 5 == 0)
317 : {
318 7 : range = range + ' ';
319 : }
320 : }
321 :
322 20 : std::int64_t standalone(0);
323 20 : bool standalone_included(rand() % 4 == 0);
324 20 : if(standalone_included)
325 : {
326 6 : if(min == std::numeric_limits<std::int64_t>::min()
327 3 : && max == std::numeric_limits<std::int64_t>::max())
328 : {
329 0 : standalone_included = false;
330 : }
331 : else
332 : {
333 3 : had_standalone = true;
334 2 : do
335 : {
336 5 : standalone = large_rnd();
337 : }
338 5 : while(standalone >= min && standalone <= max);
339 :
340 6 : std::string sep(",");
341 3 : if(rand() % 3 == 0)
342 : {
343 2 : sep = ' ' + sep;
344 : }
345 3 : if(rand() % 3 == 0)
346 : {
347 0 : sep = sep + ' ';
348 : }
349 3 : if(rand() % 2 == 0)
350 : {
351 2 : range = std::to_string(standalone) + "," + range;
352 : }
353 : else
354 : {
355 1 : range = range + "," + std::to_string(standalone);
356 : }
357 : }
358 : }
359 40 : advgetopt::string_list_t range_list;
360 40 : advgetopt::split_string(range
361 : , range_list
362 20 : , {","});
363 40 : advgetopt::validator::pointer_t integer_validator(advgetopt::validator::create("integer", range_list));
364 :
365 20 : CATCH_REQUIRE(integer_validator != nullptr);
366 20 : CATCH_REQUIRE(integer_validator->name() == "integer");
367 :
368 20020 : for(int idx(0); idx < 1000; ++idx)
369 : {
370 20000 : std::int64_t value(large_rnd());
371 :
372 : // force valid values otherwise we're likely to only have
373 : // invalid ones
374 : //
375 20000 : if(idx % 10 == 0)
376 : {
377 2000 : value %= max - min + 1;
378 2000 : value += min;
379 : }
380 18000 : else if(idx % 50 == 1 && standalone_included)
381 : {
382 60 : value = standalone;
383 : }
384 :
385 40000 : std::string const v(std::to_string(value));
386 :
387 20000 : if((standalone_included && value == standalone)
388 19940 : || (value >= min && value <= max))
389 : {
390 7526 : CATCH_REQUIRE(integer_validator->validate(v));
391 : }
392 : else
393 : {
394 12474 : CATCH_REQUIRE_FALSE(integer_validator->validate(v));
395 : }
396 :
397 20000 : if(value >= 0)
398 : {
399 9812 : if((standalone_included && value == standalone)
400 9772 : || (value >= min && value <= max))
401 : {
402 3753 : CATCH_REQUIRE(integer_validator->validate('+' + v));
403 : }
404 : else
405 : {
406 6059 : CATCH_REQUIRE_FALSE(integer_validator->validate('+' + v));
407 : }
408 : }
409 :
410 40000 : std::string const space_before(' ' + v);
411 20000 : CATCH_REQUIRE_FALSE(integer_validator->validate(space_before));
412 :
413 40000 : std::string const space_after(v + ' ');
414 20000 : CATCH_REQUIRE_FALSE(integer_validator->validate(space_after));
415 :
416 40000 : std::string const before(static_cast<char>(rand() % 26 + 'a') + v);
417 20000 : CATCH_REQUIRE_FALSE(integer_validator->validate(before));
418 :
419 40000 : std::string const after(v + static_cast<char>(rand() % 26 + 'a'));
420 20000 : CATCH_REQUIRE_FALSE(integer_validator->validate(after));
421 : }
422 : }
423 : }
424 : CATCH_END_SECTION()
425 :
426 6 : CATCH_START_SECTION("integer_validator: Verify the integer standalone list")
427 : {
428 21 : for(int count(0); count < 20; ++count)
429 : {
430 20 : int valid(rand() % 10 + 5);
431 40 : std::vector<std::int64_t> numbers;
432 20 : numbers.reserve(valid);
433 40 : std::string standalone_values;
434 198 : for(int idx(0); idx < valid; ++idx)
435 : {
436 178 : std::int64_t const value(large_rnd());
437 178 : numbers.push_back(value);
438 356 : std::string const & svalue(std::to_string(value));
439 178 : if(rand() % 5 == 0)
440 : {
441 42 : standalone_values += ' ';
442 : }
443 178 : if(idx != 0)
444 : {
445 158 : standalone_values += ',';
446 : }
447 178 : if(rand() % 5 == 0)
448 : {
449 38 : standalone_values += ' ';
450 : }
451 178 : standalone_values += svalue;
452 : }
453 20 : if(rand() % 5 == 0)
454 : {
455 5 : standalone_values += ' ';
456 : }
457 40 : advgetopt::string_list_t range_list;
458 40 : advgetopt::split_string(standalone_values
459 : , range_list
460 20 : , {","});
461 :
462 40 : advgetopt::validator::pointer_t integer_validator(advgetopt::validator::create("integer", range_list));
463 :
464 20 : CATCH_REQUIRE(integer_validator != nullptr);
465 20 : CATCH_REQUIRE(integer_validator->name() == "integer");
466 :
467 198 : for(size_t idx(0); idx < numbers.size(); ++idx)
468 : {
469 356 : std::string const svalue(std::to_string(numbers[idx]));
470 :
471 178 : CATCH_REQUIRE(integer_validator->validate(svalue));
472 : }
473 :
474 20020 : for(int idx(0); idx < 1000; ++idx)
475 : {
476 20000 : std::int64_t value;
477 :
478 : for(;;)
479 : {
480 20000 : value = large_rnd();
481 20000 : if(std::find(numbers.begin(), numbers.end(), value) == numbers.end())
482 : {
483 20000 : break;
484 : }
485 : }
486 :
487 20000 : CATCH_REQUIRE_FALSE(integer_validator->validate(std::to_string(value)));
488 : }
489 : }
490 : }
491 : CATCH_END_SECTION()
492 3 : }
493 :
494 :
495 :
496 :
497 5 : CATCH_TEST_CASE("length_validator", "[validator][valid][validation]")
498 : {
499 6 : CATCH_START_SECTION("length_validator: Verify the length validator")
500 : {
501 2 : advgetopt::validator::pointer_t length_validator(advgetopt::validator::create("length", advgetopt::string_list_t()));
502 :
503 1 : CATCH_REQUIRE(length_validator != nullptr);
504 1 : CATCH_REQUIRE(length_validator->name() == "length");
505 :
506 1 : CATCH_REQUIRE(length_validator->validate("Anything works in this case"));
507 1 : CATCH_REQUIRE(length_validator->validate("since the length won't be checked"));
508 1 : CATCH_REQUIRE(length_validator->validate(""));
509 1 : CATCH_REQUIRE(length_validator->validate("even an empty string"));
510 : }
511 : CATCH_END_SECTION()
512 :
513 6 : CATCH_START_SECTION("length_validator: Verify the length ranges")
514 : {
515 1 : bool had_standalone(false);
516 21 : for(int count(0); count < 20 || !had_standalone; ++count)
517 : {
518 20 : std::uint64_t min(rand() % 25 + 5);
519 20 : std::uint64_t max(rand() % 25 + 5);
520 20 : if(min > max)
521 : {
522 9 : std::swap(min, max);
523 : }
524 :
525 40 : std::string const & smin(std::to_string(min));
526 40 : std::string const & smax(std::to_string(max));
527 :
528 40 : std::string range("...");
529 80 : for(int three(0); three < 3; ++three)
530 : {
531 60 : if(rand() % 5 == 0)
532 : {
533 13 : range = ' ' + range;
534 : }
535 60 : if(rand() % 5 == 0)
536 : {
537 8 : range = range + ' ';
538 : }
539 : }
540 20 : range = smin + range + smax;
541 80 : for(int three(0); three < 3; ++three)
542 : {
543 60 : if(rand() % 5 == 0)
544 : {
545 8 : range = ' ' + range;
546 : }
547 60 : if(rand() % 5 == 0)
548 : {
549 10 : range = range + ' ';
550 : }
551 : }
552 :
553 20 : std::uint64_t standalone(0);
554 20 : bool const standalone_included(rand() % 4 == 0);
555 20 : if(standalone_included)
556 : {
557 6 : had_standalone = true;
558 4 : do
559 : {
560 10 : standalone = rand() % 35;
561 : }
562 10 : while(standalone >= min && standalone <= max);
563 :
564 12 : std::string sep(",");
565 6 : if(rand() % 3 == 0)
566 : {
567 3 : sep = ' ' + sep;
568 : }
569 6 : if(rand() % 3 == 0)
570 : {
571 3 : sep = sep + ' ';
572 : }
573 6 : if(rand() % 2 == 0)
574 : {
575 2 : range = std::to_string(standalone) + "," + range;
576 : }
577 : else
578 : {
579 4 : range = range + "," + std::to_string(standalone);
580 : }
581 : }
582 40 : advgetopt::string_list_t range_list;
583 40 : advgetopt::split_string(range
584 : , range_list
585 20 : , {","});
586 40 : advgetopt::validator::pointer_t length_validator(advgetopt::validator::create("length", range_list));
587 :
588 20 : CATCH_REQUIRE(length_validator != nullptr);
589 20 : CATCH_REQUIRE(length_validator->name() == "length");
590 :
591 618 : for(std::size_t idx(0); idx < std::max(max, standalone) + 5; ++idx)
592 : {
593 1196 : std::string value;
594 9417 : for(std::size_t n(0); n < idx; ++n)
595 : {
596 8819 : value += rand() % 26 + 'a';
597 : }
598 :
599 790 : if((standalone_included && value.length() == standalone)
600 1190 : || (value.length() >= min && value.length() <= max))
601 : {
602 207 : CATCH_REQUIRE(length_validator->validate(value));
603 : }
604 : else
605 : {
606 391 : CATCH_REQUIRE_FALSE(length_validator->validate(value));
607 : }
608 : }
609 : }
610 : }
611 : CATCH_END_SECTION()
612 :
613 6 : CATCH_START_SECTION("length_validator: Verify the length standalone list")
614 : {
615 21 : for(int count(0); count < 20; ++count)
616 : {
617 20 : int valid(rand() % 10 + 5);
618 40 : std::vector<std::uint64_t> string_lengths;
619 20 : string_lengths.reserve(valid);
620 40 : std::string standalone_lengths;
621 194 : for(int idx(0); idx < valid; ++idx)
622 : {
623 174 : std::int64_t const length(rand() % 25 + 5);
624 174 : string_lengths.push_back(length);
625 348 : std::string const & slength(std::to_string(length));
626 174 : if(rand() % 5 == 0)
627 : {
628 36 : standalone_lengths += ' ';
629 : }
630 174 : if(idx != 0)
631 : {
632 154 : standalone_lengths += ',';
633 : }
634 174 : if(rand() % 5 == 0)
635 : {
636 30 : standalone_lengths += ' ';
637 : }
638 174 : standalone_lengths += slength;
639 : }
640 20 : if(rand() % 5 == 0)
641 : {
642 4 : standalone_lengths += ' ';
643 : }
644 40 : advgetopt::string_list_t range_list;
645 40 : advgetopt::split_string(standalone_lengths
646 : , range_list
647 20 : , {","});
648 :
649 40 : advgetopt::validator::pointer_t length_validator(advgetopt::validator::create("length", range_list));
650 :
651 20 : CATCH_REQUIRE(length_validator != nullptr);
652 20 : CATCH_REQUIRE(length_validator->name() == "length");
653 :
654 194 : for(std::size_t idx(0); idx < string_lengths.size(); ++idx)
655 : {
656 348 : std::string value;
657 3244 : for(std::uint64_t n(0); n < string_lengths[idx]; ++n)
658 : {
659 3070 : value += rand() % 26 + 'a';
660 : }
661 174 : CATCH_REQUIRE(length_validator->validate(value));
662 : }
663 :
664 20 : std::size_t const longest(*std::max_element(string_lengths.begin(), string_lengths.end()));
665 674 : for(std::size_t idx(0); idx <= longest + 5; ++idx)
666 : {
667 654 : if(std::find(string_lengths.begin(), string_lengths.end(), idx) != string_lengths.end())
668 : {
669 140 : continue;
670 : }
671 :
672 1028 : std::string value;
673 8456 : for(std::size_t n(0); n < idx; ++n)
674 : {
675 7942 : value += rand() % 26 + 'a';
676 : }
677 :
678 514 : CATCH_REQUIRE_FALSE(length_validator->validate(value));
679 : }
680 : }
681 : }
682 : CATCH_END_SECTION()
683 3 : }
684 :
685 :
686 :
687 :
688 3 : CATCH_TEST_CASE("multi_validators", "[validator][valid][validation]")
689 : {
690 2 : CATCH_START_SECTION("multi_validators: Verify an integer along a few keywords")
691 : {
692 2 : advgetopt::validator::pointer_t list_validator(advgetopt::validator::create("keywords(off,min,max) | integer(1...100)"));
693 :
694 1 : CATCH_REQUIRE(list_validator != nullptr);
695 1 : CATCH_REQUIRE(list_validator->name() == "list");
696 :
697 1 : CATCH_REQUIRE(list_validator->validate("off"));
698 1 : CATCH_REQUIRE(list_validator->validate("min"));
699 1 : CATCH_REQUIRE(list_validator->validate("max"));
700 :
701 122 : for(int idx(-10); idx <= 110; ++idx)
702 : {
703 242 : std::string const v(std::to_string(idx));
704 :
705 121 : if(idx < 1 || idx > 100)
706 : {
707 21 : CATCH_REQUIRE_FALSE(list_validator->validate(v));
708 : }
709 : else
710 : {
711 100 : CATCH_REQUIRE(list_validator->validate(v));
712 : }
713 : }
714 : }
715 : CATCH_END_SECTION()
716 1 : }
717 :
718 :
719 :
720 3 : CATCH_TEST_CASE("keywords_validator", "[validator][valid][validation]")
721 : {
722 2 : CATCH_START_SECTION("keywords_validator: Verify simple keywords")
723 : {
724 2 : advgetopt::validator::pointer_t list_validator(advgetopt::validator::create("keywords(angle, corner ,, ceiling)"));
725 :
726 1 : CATCH_REQUIRE(list_validator != nullptr);
727 1 : CATCH_REQUIRE(list_validator->name() == "keywords");
728 :
729 1 : CATCH_REQUIRE(list_validator->validate("angle"));
730 1 : CATCH_REQUIRE(list_validator->validate("corner"));
731 1 : CATCH_REQUIRE(list_validator->validate("ceiling"));
732 :
733 1 : CATCH_REQUIRE_FALSE(list_validator->validate(""));
734 1 : CATCH_REQUIRE_FALSE(list_validator->validate("other"));
735 : }
736 : CATCH_END_SECTION()
737 1 : }
738 :
739 :
740 :
741 :
742 5 : CATCH_TEST_CASE("double_validator", "[validator][valid][validation]")
743 : {
744 6 : CATCH_START_SECTION("Verify the double validator")
745 2 : advgetopt::validator::pointer_t double_validator(advgetopt::validator::create("double", advgetopt::string_list_t()));
746 :
747 1 : CATCH_REQUIRE(double_validator != nullptr);
748 1 : CATCH_REQUIRE(double_validator->name() == "double");
749 :
750 1 : CATCH_REQUIRE_FALSE(double_validator->validate(""));
751 1 : CATCH_REQUIRE_FALSE(double_validator->validate("+"));
752 1 : CATCH_REQUIRE_FALSE(double_validator->validate("-"));
753 1 : CATCH_REQUIRE_FALSE(double_validator->validate("alpha"));
754 :
755 1001 : for(int idx(0); idx < 1000; ++idx)
756 : {
757 1000 : double value(static_cast<double>(large_rnd()) / static_cast<double>(large_rnd(false)));
758 2000 : std::string const v(std::to_string(value));
759 :
760 1000 : CATCH_REQUIRE(double_validator->validate(v));
761 :
762 1000 : if(value >= 0)
763 : {
764 522 : CATCH_REQUIRE(double_validator->validate('+' + v));
765 : }
766 :
767 2000 : std::string const space_before(' ' + v);
768 1000 : CATCH_REQUIRE_FALSE(double_validator->validate(space_before));
769 :
770 2000 : std::string const space_after(v + ' ');
771 1000 : CATCH_REQUIRE_FALSE(double_validator->validate(space_after));
772 :
773 2000 : std::string const before(static_cast<char>(rand() % 26 + 'a') + v);
774 1000 : CATCH_REQUIRE_FALSE(double_validator->validate(before));
775 :
776 2000 : std::string const after(v + static_cast<char>(rand() % 26 + 'a'));
777 1000 : CATCH_REQUIRE_FALSE(double_validator->validate(after));
778 : }
779 : CATCH_END_SECTION()
780 :
781 6 : CATCH_START_SECTION("Verify the double ranges")
782 1 : bool had_standalone(false);
783 21 : for(int count(0); count < 20 || !had_standalone; ++count)
784 : {
785 20 : double min(static_cast<double>(large_rnd()) / static_cast<double>(large_rnd(false)));
786 20 : double max(static_cast<double>(large_rnd()) / static_cast<double>(large_rnd(false)));
787 20 : if(min > max)
788 : {
789 10 : std::swap(min, max);
790 : }
791 :
792 40 : std::string const & smin(std::to_string(min));
793 40 : std::string const & smax(std::to_string(max));
794 :
795 40 : std::string range("...");
796 80 : for(int three(0); three < 3; ++three)
797 : {
798 60 : if(rand() % 5 == 0)
799 : {
800 13 : range = ' ' + range;
801 : }
802 60 : if(rand() % 5 == 0)
803 : {
804 9 : range = range + ' ';
805 : }
806 : }
807 20 : range = smin + range + smax;
808 80 : for(int three(0); three < 3; ++three)
809 : {
810 60 : if(rand() % 5 == 0)
811 : {
812 16 : range = ' ' + range;
813 : }
814 60 : if(rand() % 5 == 0)
815 : {
816 7 : range = range + ' ';
817 : }
818 : }
819 :
820 20 : double standalone(0);
821 20 : bool standalone_included(rand() % 4 == 0);
822 20 : if(standalone_included)
823 : {
824 10 : if(min <= std::numeric_limits<double>::min()
825 5 : && max >= std::numeric_limits<double>::max())
826 : {
827 0 : standalone_included = false;
828 : }
829 : else
830 : {
831 5 : had_standalone = true;
832 0 : do
833 : {
834 5 : standalone = static_cast<double>(large_rnd()) / static_cast<double>(large_rnd(false));
835 : }
836 5 : while(standalone >= min && standalone <= max);
837 :
838 10 : std::string sep(",");
839 5 : if(rand() % 3 == 0)
840 : {
841 1 : sep = ' ' + sep;
842 : }
843 5 : if(rand() % 3 == 0)
844 : {
845 1 : sep = sep + ' ';
846 : }
847 5 : if(rand() % 2 == 0)
848 : {
849 1 : range = std::to_string(standalone) + "," + range;
850 : }
851 : else
852 : {
853 4 : range = range + "," + std::to_string(standalone);
854 : }
855 : }
856 : }
857 40 : advgetopt::string_list_t range_list;
858 40 : advgetopt::split_string(range
859 : , range_list
860 20 : , {","});
861 40 : advgetopt::validator::pointer_t double_validator(advgetopt::validator::create("double", range_list));
862 :
863 20 : CATCH_REQUIRE(double_validator != nullptr);
864 20 : CATCH_REQUIRE(double_validator->name() == "double");
865 :
866 20020 : for(int idx(0); idx < 1000; ++idx)
867 : {
868 20000 : double value(static_cast<double>(large_rnd()) / static_cast<double>(large_rnd(false)));
869 :
870 : // force valid values otherwise we're likely to only have
871 : // invalid ones
872 : //
873 20000 : if(idx % 10 == 0)
874 : {
875 2000 : value = fmod(value, max - min + 1.0) + min;
876 : }
877 18000 : else if(idx % 50 == 1 && standalone_included)
878 : {
879 100 : value = standalone;
880 : }
881 :
882 40000 : std::string const v(std::to_string(value));
883 :
884 : #pragma GCC diagnostic push
885 : #pragma GCC diagnostic ignored "-Wfloat-equal"
886 20000 : if((standalone_included && value == standalone)
887 19900 : || (value >= min && value <= max))
888 : {
889 5105 : CATCH_REQUIRE(double_validator->validate(v));
890 : }
891 : else
892 : {
893 14895 : CATCH_REQUIRE_FALSE(double_validator->validate(v));
894 : }
895 :
896 20000 : if(value >= 0.0)
897 : {
898 9824 : if((standalone_included && value == standalone)
899 9784 : || (value >= min && value <= max))
900 : {
901 3406 : CATCH_REQUIRE(double_validator->validate('+' + v));
902 : }
903 : else
904 : {
905 6418 : CATCH_REQUIRE_FALSE(double_validator->validate('+' + v));
906 : }
907 : }
908 : #pragma GCC diagnostic pop
909 :
910 40000 : std::string const space_before(' ' + v);
911 20000 : CATCH_REQUIRE_FALSE(double_validator->validate(space_before));
912 :
913 40000 : std::string const space_after(v + ' ');
914 20000 : CATCH_REQUIRE_FALSE(double_validator->validate(space_after));
915 :
916 40000 : std::string const before(static_cast<char>(rand() % 26 + 'a') + v);
917 20000 : CATCH_REQUIRE_FALSE(double_validator->validate(before));
918 :
919 40000 : std::string const after(v + static_cast<char>(rand() % 26 + 'a'));
920 20000 : CATCH_REQUIRE_FALSE(double_validator->validate(after));
921 : }
922 : }
923 : CATCH_END_SECTION()
924 :
925 6 : CATCH_START_SECTION("Verify the double standalone list")
926 21 : for(int count(0); count < 20; ++count)
927 : {
928 20 : int valid(rand() % 10 + 5);
929 40 : std::vector<double> numbers;
930 20 : numbers.reserve(valid);
931 40 : std::string standalone_values;
932 205 : for(int idx(0); idx < valid; ++idx)
933 : {
934 185 : double const value(static_cast<double>(large_rnd()) / static_cast<double>(large_rnd(false)));
935 185 : numbers.push_back(value);
936 370 : std::string const & svalue(std::to_string(value));
937 185 : if(rand() % 5 == 0)
938 : {
939 32 : standalone_values += ' ';
940 : }
941 185 : if(idx != 0)
942 : {
943 165 : standalone_values += ',';
944 : }
945 185 : if(rand() % 5 == 0)
946 : {
947 40 : standalone_values += ' ';
948 : }
949 185 : standalone_values += svalue;
950 : }
951 20 : if(rand() % 5 == 0)
952 : {
953 8 : standalone_values += ' ';
954 : }
955 40 : advgetopt::string_list_t range_list;
956 40 : advgetopt::split_string(standalone_values
957 : , range_list
958 20 : , {","});
959 :
960 40 : advgetopt::validator::pointer_t double_validator(advgetopt::validator::create("double", range_list));
961 :
962 20 : CATCH_REQUIRE(double_validator != nullptr);
963 20 : CATCH_REQUIRE(double_validator->name() == "double");
964 :
965 205 : for(size_t idx(0); idx < numbers.size(); ++idx)
966 : {
967 370 : std::string const svalue(std::to_string(numbers[idx]));
968 :
969 185 : CATCH_REQUIRE(double_validator->validate(svalue));
970 : }
971 :
972 20020 : for(int idx(0); idx < 1000; ++idx)
973 : {
974 20000 : std::int64_t value;
975 :
976 : for(;;)
977 : {
978 20000 : value = static_cast<double>(large_rnd()) / static_cast<double>(large_rnd(false));
979 20000 : if(std::find(numbers.begin(), numbers.end(), value) == numbers.end())
980 : {
981 20000 : break;
982 : }
983 : }
984 :
985 20000 : CATCH_REQUIRE_FALSE(double_validator->validate(std::to_string(value)));
986 : }
987 : }
988 : CATCH_END_SECTION()
989 3 : }
990 :
991 :
992 :
993 :
994 5 : CATCH_TEST_CASE("duration_validator", "[validator][valid][validation]")
995 : {
996 6 : CATCH_START_SECTION("Verify the duration validator (simple values)")
997 : {
998 1 : double duration(0.0);
999 :
1000 : // simple seconds with decimal point
1001 : //
1002 1 : CATCH_REQUIRE(advgetopt::validator_duration::convert_string("22.3s", 0, duration));
1003 1 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(duration, 22.3, 0.0));
1004 :
1005 : // "seconds" is the default
1006 : //
1007 1 : CATCH_REQUIRE(advgetopt::validator_duration::convert_string("1.05", 0, duration));
1008 1 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(duration, 1.05, 0.0));
1009 :
1010 : // number can start with a decimal point
1011 : //
1012 1 : CATCH_REQUIRE(advgetopt::validator_duration::convert_string(".0503", 0, duration));
1013 1 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(duration, 0.0503, 0.0));
1014 : }
1015 : CATCH_END_SECTION()
1016 :
1017 6 : CATCH_START_SECTION("Verify the duration validator (multiple values)")
1018 : {
1019 1 : double duration(0.0);
1020 1 : CATCH_REQUIRE(advgetopt::validator_duration::convert_string("1d 3h 2m 15.3s", 0, duration));
1021 1 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(duration, 1.0 * 86400.0 + 3.0 * 3600.0 + 2.0 * 60.0 + 15.3, 0.0));
1022 :
1023 : // same in uppercase
1024 1 : CATCH_REQUIRE(advgetopt::validator_duration::convert_string("1D 3H 2M 15.3S", 0, duration));
1025 1 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(duration, 1.0 * 86400.0 + 3.0 * 3600.0 + 2.0 * 60.0 + 15.3, 0.0));
1026 :
1027 1 : CATCH_REQUIRE(advgetopt::validator_duration::convert_string("3d 15h 52m 21.801s", 0, duration));
1028 1 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(duration, 3.0 * 86400.0 + 15.0 * 3600.0 + 52.0 * 60.0 + 21.801, 0.0));
1029 : }
1030 : CATCH_END_SECTION()
1031 :
1032 6 : CATCH_START_SECTION("Verify the duration validator (one value)")
1033 : {
1034 : // this test does not verify that double conversion works since we
1035 : // have a separate test for that specific validator
1036 : //
1037 4 : for(int size(0); size < 3; ++size)
1038 : {
1039 3 : advgetopt::validator_duration::flag_t flg(advgetopt::validator_duration::VALIDATOR_DURATION_DEFAULT_FLAGS);
1040 6 : advgetopt::string_list_t flags;
1041 3 : if(size == 1)
1042 : {
1043 1 : flags.push_back("small");
1044 : }
1045 2 : else if(size == 2)
1046 : {
1047 1 : flags.push_back("large");
1048 1 : flg = advgetopt::validator_duration::VALIDATOR_DURATION_LONG;
1049 : }
1050 6 : advgetopt::validator::pointer_t duration_validator(advgetopt::validator::create("duration", flags));
1051 :
1052 3 : CATCH_REQUIRE(duration_validator != nullptr);
1053 3 : CATCH_REQUIRE(duration_validator->name() == "duration");
1054 :
1055 3003 : for(int idx(0); idx < 1000; ++idx)
1056 : {
1057 : // use smaller values between 0 and 1
1058 : // (the loop is to make sure we don't end up with "123e-10"
1059 : // type of numbers... which do not work here)
1060 : //
1061 3000 : double value(0.0);
1062 : #pragma GCC diagnostic push
1063 : #pragma GCC diagnostic ignored "-Wfloat-equal"
1064 0 : do
1065 : {
1066 3000 : value = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
1067 : }
1068 3000 : while(value < 0.0001 && value != 0.0);
1069 : #pragma GCC diagnostic pop
1070 3000 : if(rand() % 2 == 0)
1071 : {
1072 1515 : value *= -1.0;
1073 : }
1074 6000 : std::stringstream ss;
1075 3000 : ss.precision(std::numeric_limits<double>::max_digits10);
1076 3000 : ss << value;
1077 6000 : std::string const v(ss.str());
1078 :
1079 66000 : for(std::size_t i(0); i < std::size(g_duration_suffixes); ++i)
1080 : {
1081 441000 : for(int j(0); j <= 5; ++j)
1082 : {
1083 756000 : std::string duration(v);
1084 1323000 : for(int k(0); k < j; ++k)
1085 : {
1086 : // any number of spaces in between are allowed
1087 : //
1088 945000 : duration += ' ';
1089 : }
1090 378000 : duration += g_duration_suffixes[i].f_suffix;
1091 :
1092 378000 : CATCH_REQUIRE(duration_validator->validate(duration));
1093 378000 : if(value >= 0)
1094 : {
1095 187110 : CATCH_REQUIRE(duration_validator->validate('+' + duration));
1096 : }
1097 :
1098 378000 : double result(0.0);
1099 378000 : CATCH_REQUIRE(advgetopt::validator_duration::convert_string(duration, flg, result));
1100 378000 : if(g_duration_suffixes[i].f_factor < 0.0)
1101 : {
1102 : // the 'm' special case
1103 : //
1104 18000 : if(size == 2)
1105 : {
1106 : // 'large' -- 1 month
1107 : //
1108 6000 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(result, value * (86400.0 * 30.0)));
1109 : }
1110 : else
1111 : {
1112 : // 'small' -- 1 minute
1113 : //
1114 12000 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(result, value * 60.0));
1115 : }
1116 : }
1117 : else
1118 : {
1119 360000 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::nearly_equal(result, value * g_duration_suffixes[i].f_factor));
1120 : }
1121 : }
1122 : }
1123 : }
1124 : }
1125 : }
1126 : CATCH_END_SECTION()
1127 3 : }
1128 :
1129 :
1130 :
1131 :
1132 3 : CATCH_TEST_CASE("size_validator", "[validator][valid][validation]")
1133 : {
1134 : #pragma GCC diagnostic push
1135 : #pragma GCC diagnostic ignored "-Wpedantic"
1136 2 : CATCH_START_SECTION("Verify the size validator")
1137 : {
1138 : // this test does not verify that double conversion works since we
1139 : // have a separate test for that specific validator
1140 : //
1141 4 : for(int mode(0); mode < 3; ++mode)
1142 : {
1143 3 : advgetopt::validator_size::flag_t flg(advgetopt::validator_size::VALIDATOR_SIZE_DEFAULT_FLAGS);
1144 6 : advgetopt::string_list_t flags;
1145 3 : if(mode == 1)
1146 : {
1147 1 : flags.push_back("si");
1148 : }
1149 2 : else if(mode == 2)
1150 : {
1151 1 : flags.push_back("legacy");
1152 1 : flg = advgetopt::validator_size::VALIDATOR_SIZE_POWER_OF_TWO;
1153 : }
1154 6 : advgetopt::validator::pointer_t size_validator(advgetopt::validator::create("size", flags));
1155 :
1156 3 : CATCH_REQUIRE(size_validator != nullptr);
1157 3 : CATCH_REQUIRE(size_validator->name() == "size");
1158 :
1159 3003 : for(int idx(0); idx < 1000; ++idx)
1160 : {
1161 : // use smaller values between 0 and about 5
1162 : //
1163 3000 : double value(static_cast<double>(rand()) / static_cast<double>(RAND_MAX / 5));
1164 3000 : if(rand() % 2 == 0)
1165 : {
1166 1483 : value *= -1.0;
1167 : }
1168 6000 : std::stringstream ss;
1169 3000 : ss.precision(std::numeric_limits<double>::max_digits10);
1170 3000 : ss << value;
1171 6000 : std::string const v(ss.str());
1172 :
1173 57000 : for(std::size_t i(0); i < std::size(g_size_suffixes); ++i)
1174 : {
1175 378000 : for(int j(0); j <= 5; ++j)
1176 : {
1177 648000 : std::string size(v);
1178 1134000 : for(int k(0); k < j; ++k)
1179 : {
1180 : // any number of spaces in between are allowed
1181 : //
1182 810000 : size += ' ';
1183 : }
1184 324000 : size += g_size_suffixes[i].f_suffix;
1185 :
1186 324000 : CATCH_REQUIRE(size_validator->validate(size));
1187 324000 : if(value >= 0)
1188 : {
1189 163836 : CATCH_REQUIRE(size_validator->validate('+' + size));
1190 : }
1191 :
1192 324000 : __int128 result(0.0);
1193 324000 : CATCH_REQUIRE(advgetopt::validator_size::convert_string(size, flg, result));
1194 :
1195 324000 : long double const base(mode == 2 ? 1024.0L : g_size_suffixes[i].f_base);
1196 324000 : long double expected(1);
1197 1620000 : for(int p(0); p < g_size_suffixes[i].f_power; ++p)
1198 : {
1199 1296000 : expected *= base;
1200 : }
1201 324000 : __int128 int_expected(expected * static_cast<long double>(value));
1202 :
1203 : //std::cerr << "converted [" << size << "] to [" << result << "] wanted [" << int_expected << "]\n";
1204 324000 : CATCH_REQUIRE(result == int_expected);
1205 : }
1206 : }
1207 : }
1208 : }
1209 : }
1210 : CATCH_END_SECTION()
1211 : #pragma GCC diagnostic pop
1212 1 : }
1213 :
1214 :
1215 :
1216 :
1217 6 : CATCH_TEST_CASE("regex_validator", "[validator][valid][validation]")
1218 : {
1219 8 : CATCH_START_SECTION("regex_validator: Verify the regex validator")
1220 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("regex", {".*@.*\\..*"}));
1221 :
1222 1 : CATCH_REQUIRE(regex_validator != nullptr);
1223 1 : CATCH_REQUIRE(regex_validator->name() == "regex");
1224 :
1225 1 : CATCH_REQUIRE(regex_validator->validate("@m2osw."));
1226 1 : CATCH_REQUIRE(regex_validator->validate("contact@m2osw.com"));
1227 1 : CATCH_REQUIRE(regex_validator->validate("Contact@m2osw.com"));
1228 1 : CATCH_REQUIRE(regex_validator->validate("Contact@M2OSW.com"));
1229 :
1230 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact@m2osw:com"));
1231 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact!m2osw.com"));
1232 : CATCH_END_SECTION()
1233 :
1234 8 : CATCH_START_SECTION("regex_validator: Verify the regex string (case sensitive)")
1235 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("regex", {"/contact@.*\\..*/"}));
1236 :
1237 1 : CATCH_REQUIRE(regex_validator != nullptr);
1238 1 : CATCH_REQUIRE(regex_validator->name() == "regex");
1239 :
1240 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("@m2osw."));
1241 1 : CATCH_REQUIRE(regex_validator->validate("contact@m2osw.com"));
1242 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("Contact@m2osw.com"));
1243 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("Contact@M2OSW.com"));
1244 :
1245 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact@m2osw:com"));
1246 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact!m2osw.com"));
1247 : CATCH_END_SECTION()
1248 :
1249 8 : CATCH_START_SECTION("regex_validator: Verify the regex string (case insensitive)")
1250 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("regex", {"/contact@.*\\..*/i"}));
1251 :
1252 1 : CATCH_REQUIRE(regex_validator != nullptr);
1253 1 : CATCH_REQUIRE(regex_validator->name() == "regex");
1254 :
1255 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("@m2osw."));
1256 1 : CATCH_REQUIRE(regex_validator->validate("contact@m2osw.com"));
1257 1 : CATCH_REQUIRE(regex_validator->validate("Contact@m2osw.com"));
1258 1 : CATCH_REQUIRE(regex_validator->validate("Contact@M2OSW.com"));
1259 :
1260 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact@m2osw:com"));
1261 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact!m2osw.com"));
1262 : CATCH_END_SECTION()
1263 :
1264 8 : CATCH_START_SECTION("regex_validator: Verify direct regex string (case insensitive)")
1265 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("/contact@.*\\..*/i"));
1266 :
1267 1 : CATCH_REQUIRE(regex_validator != nullptr);
1268 1 : CATCH_REQUIRE(regex_validator->name() == "regex");
1269 :
1270 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("@m2osw."));
1271 1 : CATCH_REQUIRE(regex_validator->validate("contact@m2osw.com"));
1272 1 : CATCH_REQUIRE(regex_validator->validate("Contact@m2osw.com"));
1273 1 : CATCH_REQUIRE(regex_validator->validate("Contact@M2OSW.com"));
1274 :
1275 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact@m2osw:com"));
1276 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact!m2osw.com"));
1277 : CATCH_END_SECTION()
1278 4 : }
1279 :
1280 :
1281 :
1282 :
1283 :
1284 :
1285 :
1286 :
1287 3 : CATCH_TEST_CASE("invalid_validator_factory", "[validator][invalid][validation]")
1288 : {
1289 2 : CATCH_START_SECTION("invalid_validator_factory: Register duplicated factories")
1290 : {
1291 0 : class duplicate_integer
1292 : : public advgetopt::validator
1293 : {
1294 : public:
1295 0 : virtual std::string name() const override
1296 : {
1297 0 : return "integer";
1298 : }
1299 :
1300 0 : virtual bool validate(std::string const & value) const override
1301 : {
1302 0 : return value == "123";
1303 : }
1304 : };
1305 3 : class duplicate_factory
1306 : : public advgetopt::validator_factory
1307 : {
1308 : public:
1309 2 : virtual std::string get_name() const override
1310 : {
1311 2 : return "integer";
1312 : }
1313 :
1314 0 : virtual std::shared_ptr<advgetopt::validator> create(advgetopt::string_list_t const & data) const override
1315 : {
1316 0 : snapdev::NOT_USED(data); // ignore `data`
1317 0 : return std::make_shared<duplicate_integer>();
1318 : }
1319 : };
1320 2 : std::unique_ptr<advgetopt::validator_factory> factory(new duplicate_factory());
1321 1 : CATCH_REQUIRE_THROWS_MATCHES(
1322 : advgetopt::validator::register_validator(*factory.get())
1323 : , advgetopt::getopt_logic_error
1324 : , Catch::Matchers::ExceptionMessage(
1325 : "getopt_logic_error: you have two or more validator factories named \"integer\"."));
1326 : }
1327 : CATCH_END_SECTION()
1328 1 : }
1329 :
1330 3 : CATCH_TEST_CASE("invalid_validator_create", "[validator][invalid][validation]")
1331 : {
1332 2 : CATCH_START_SECTION("invalid_validator_create: Verify missing ')' in string based create")
1333 : {
1334 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): parameter list must end with ')'. Remaining input: \"...EOS\"");
1335 2 : advgetopt::validator::pointer_t validator(advgetopt::validator::create("integer(1...7, 11...15"));
1336 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1337 1 : CATCH_REQUIRE(validator == nullptr);
1338 :
1339 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): parameter list must end with ')'. Remaining input: \"...EOS\"");
1340 1 : validator = advgetopt::validator::create("regex([a-z]+");
1341 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1342 1 : CATCH_REQUIRE(validator == nullptr);
1343 :
1344 1 : validator = advgetopt::validator::create(" ");
1345 1 : CATCH_REQUIRE(validator == nullptr);
1346 :
1347 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): expected a regex, an identifier or a string inside the () of a parameter. Remaining input: \"[a-z]+))\"");
1348 1 : validator = advgetopt::validator::create("regex(([a-z]+))");
1349 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1350 1 : CATCH_REQUIRE(validator == nullptr);
1351 :
1352 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): parameters must be separated by ','. Remaining input: \"...EOS\"");
1353 1 : validator = advgetopt::validator::create("keywords(foo, blah error)");
1354 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1355 1 : CATCH_REQUIRE(validator == nullptr);
1356 :
1357 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): unexpected token in validator definition; expected an identifier. Remaining input: \"missing, name)\".");
1358 1 : validator = advgetopt::validator::create("(missing, name)");
1359 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1360 1 : CATCH_REQUIRE(validator == nullptr);
1361 :
1362 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): unexpected character for an identifier (10).");
1363 1 : validator = advgetopt::validator::create("keywords(missing, name)\n|\ninteger(33)");
1364 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1365 1 : CATCH_REQUIRE(validator == nullptr);
1366 :
1367 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): validator definitions must be separated by '|'. Remaining input: \"33)\"");
1368 1 : validator = advgetopt::validator::create("keywords(missing, name) integer(33)");
1369 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1370 1 : CATCH_REQUIRE(validator == nullptr);
1371 : }
1372 : CATCH_END_SECTION()
1373 1 : }
1374 :
1375 3 : CATCH_TEST_CASE("invalid_integer_validator", "[validator][invalid][validation]")
1376 : {
1377 2 : CATCH_START_SECTION("invalid_integer_validator: Verify invalid integer ranges")
1378 : {
1379 1 : advgetopt::string_list_t range{
1380 : "abc",
1381 : "abc...6",
1382 : "3...def",
1383 2 : "10...1"};
1384 :
1385 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: abc is not a valid standalone value for your ranges; it must only be digits, optionally preceeded by a sign (+ or -) and not overflow an int64_t value.");
1386 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: abc is not a valid value for your range's start; it must only be digits, optionally preceeded by a sign (+ or -) and not overflow an int64_t value.");
1387 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: def is not a valid value for your range's end; it must only be digits, optionally preceeded by a sign (+ or -) and not overflow an int64_t value.");
1388 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: 10 has to be smaller or equal to 1; you have an invalid range.");
1389 :
1390 2 : advgetopt::validator::pointer_t integer_validator(advgetopt::validator::create("integer", range));
1391 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1392 : }
1393 : CATCH_END_SECTION()
1394 1 : }
1395 :
1396 3 : CATCH_TEST_CASE("invalid_double_validator", "[validator][invalid][validation]")
1397 : {
1398 2 : CATCH_START_SECTION("invalid_double_validator: Verify invalid double ranges")
1399 : {
1400 1 : advgetopt::string_list_t range{
1401 : "abc",
1402 : "abc...6.3",
1403 : "13.3...def",
1404 2 : "10.5...1.2"};
1405 :
1406 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: abc is not a valid standalone value; it must be a valid floating point, optionally preceeded by a sign (+ or -).");
1407 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: abc is not a valid value for your range's start; it must be a valid floating point, optionally preceeded by a sign (+ or -).");
1408 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: def is not a valid value for your range's end; it must be a valid floating point, optionally preceeded by a sign (+ or -).");
1409 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: 10.5 has to be smaller or equal to 1.2; you have an invalid range.");
1410 :
1411 2 : advgetopt::validator::pointer_t integer_validator(advgetopt::validator::create("double", range));
1412 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1413 : }
1414 : CATCH_END_SECTION()
1415 1 : }
1416 :
1417 3 : CATCH_TEST_CASE("invalid_duration_validator", "[invalid][validation]")
1418 : {
1419 2 : CATCH_START_SECTION("invalid_duration_validator: Verify invalid duration flags")
1420 : {
1421 1 : advgetopt::string_list_t range{
1422 : "small",
1423 : "medium",
1424 2 : "large"};
1425 :
1426 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: medium is not a valid flag for the duration validator.");
1427 2 : advgetopt::validator::pointer_t duration_validator(advgetopt::validator::create("duration", range));
1428 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1429 :
1430 1 : CATCH_REQUIRE_FALSE(duration_validator->validate(""));
1431 1 : CATCH_REQUIRE_FALSE(duration_validator->validate(" "));
1432 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("+"));
1433 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("-"));
1434 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("alpha"));
1435 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("3.5 beta"));
1436 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("7.5delta"));
1437 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("+8.1 gamma"));
1438 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("-2.3eta"));
1439 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("-202.3 HERO"));
1440 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("-7.31Hr"));
1441 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("-1.32mom"));
1442 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("-5.36 secs"));
1443 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("28.901 wkS"));
1444 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("28 YY"));
1445 1 : CATCH_REQUIRE_FALSE(duration_validator->validate("2..8 year"));
1446 : }
1447 : CATCH_END_SECTION()
1448 1 : }
1449 :
1450 :
1451 :
1452 3 : CATCH_TEST_CASE("invalid_email_validator", "[invalid][validation]")
1453 : {
1454 2 : CATCH_START_SECTION("invalid_email_validator: Verify emails with invalid parameters.")
1455 : {
1456 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator_email() supports zero or one parameter.");
1457 2 : advgetopt::validator::pointer_t keywords(advgetopt::validator::create("email(single, multiple)"));
1458 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1459 1 : CATCH_REQUIRE(keywords != nullptr);
1460 :
1461 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator_email(): unknown parameter \"orange\".");
1462 1 : keywords = advgetopt::validator::create("email(orange)");
1463 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1464 1 : CATCH_REQUIRE(keywords != nullptr);
1465 : }
1466 : CATCH_END_SECTION()
1467 1 : }
1468 :
1469 :
1470 :
1471 3 : CATCH_TEST_CASE("invalid_keywords_validator", "[invalid][validation]")
1472 : {
1473 2 : CATCH_START_SECTION("invalid_keywords_validator: Verify that keywords without parameters fail.")
1474 : {
1475 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator_keywords() requires at least one parameter.");
1476 2 : advgetopt::validator::pointer_t keywords(advgetopt::validator::create("keywords"));
1477 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1478 1 : CATCH_REQUIRE(keywords != nullptr);
1479 :
1480 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator_keywords() requires at least one parameter.");
1481 1 : keywords = advgetopt::validator::create("keywords()");
1482 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1483 1 : CATCH_REQUIRE(keywords != nullptr);
1484 : }
1485 : CATCH_END_SECTION()
1486 1 : }
1487 :
1488 :
1489 :
1490 3 : CATCH_TEST_CASE("invalid_list_validator", "[invalid][validation]")
1491 : {
1492 2 : CATCH_START_SECTION("invalid_list_validator: Verify that list validators do not accept parameters.")
1493 : {
1494 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator_list() does not support any parameter.");
1495 2 : advgetopt::validator::pointer_t list(advgetopt::validator::create("list(with, parameters)"));
1496 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1497 1 : CATCH_REQUIRE(list != nullptr);
1498 : }
1499 : CATCH_END_SECTION()
1500 1 : }
1501 :
1502 :
1503 :
1504 3 : CATCH_TEST_CASE("invalid_size_validator", "[invalid][validation]")
1505 : {
1506 2 : CATCH_START_SECTION("invalid_size_validator: Verify invalid duration flags")
1507 : {
1508 1 : advgetopt::string_list_t flags{
1509 : "si",
1510 : "future",
1511 2 : "legacy"};
1512 :
1513 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: future is not a valid flag for the size validator.");
1514 2 : advgetopt::validator::pointer_t size_validator(advgetopt::validator::create("size", flags));
1515 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1516 :
1517 1 : CATCH_REQUIRE_FALSE(size_validator->validate(""));
1518 1 : CATCH_REQUIRE_FALSE(size_validator->validate(" "));
1519 1 : CATCH_REQUIRE_FALSE(size_validator->validate("+"));
1520 1 : CATCH_REQUIRE_FALSE(size_validator->validate("-"));
1521 1 : CATCH_REQUIRE_FALSE(size_validator->validate("size"));
1522 1 : CATCH_REQUIRE_FALSE(size_validator->validate("3.5 large"));
1523 1 : CATCH_REQUIRE_FALSE(size_validator->validate("-1.31body"));
1524 1 : CATCH_REQUIRE_FALSE(size_validator->validate("7.5small"));
1525 1 : CATCH_REQUIRE_FALSE(size_validator->validate("+8.1 tiny"));
1526 1 : CATCH_REQUIRE_FALSE(size_validator->validate("-2.3medium"));
1527 1 : CATCH_REQUIRE_FALSE(size_validator->validate("1000kbit"));
1528 1 : CATCH_REQUIRE_FALSE(size_validator->validate("7 monster"));
1529 1 : CATCH_REQUIRE_FALSE(size_validator->validate("-101.101egret"));
1530 1 : CATCH_REQUIRE_FALSE(size_validator->validate("11 products"));
1531 1 : CATCH_REQUIRE_FALSE(size_validator->validate("1.01 tractor"));
1532 1 : CATCH_REQUIRE_FALSE(size_validator->validate("+7.0 years"));
1533 1 : CATCH_REQUIRE_FALSE(size_validator->validate("-51.7zeroes"));
1534 1 : CATCH_REQUIRE_FALSE(size_validator->validate("+121gruffalos"));
1535 1 : CATCH_REQUIRE_FALSE(size_validator->validate("++1.7 KiB"));
1536 1 : CATCH_REQUIRE_FALSE(size_validator->validate("-+3.1 MiB"));
1537 1 : CATCH_REQUIRE_FALSE(size_validator->validate("+-9.2 GiB"));
1538 1 : CATCH_REQUIRE_FALSE(size_validator->validate("--19.4 PiB"));
1539 1 : CATCH_REQUIRE_FALSE(size_validator->validate("-3.5.4B"));
1540 : }
1541 : CATCH_END_SECTION()
1542 1 : }
1543 :
1544 8 : CATCH_TEST_CASE("invalid_regex_validator", "[validator][invalid][validation]")
1545 : {
1546 12 : CATCH_START_SECTION("invalid_regex_validator: Verify invalid regex flags")
1547 : {
1548 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag f in regular expression \"/contact@.*\\..*/f\".");
1549 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("regex", {"/contact@.*\\..*/f"}));
1550 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1551 :
1552 1 : CATCH_REQUIRE(regex_validator != nullptr);
1553 1 : CATCH_REQUIRE(regex_validator->name() == "regex");
1554 :
1555 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("@m2osw."));
1556 1 : CATCH_REQUIRE(regex_validator->validate("contact@m2osw.com"));
1557 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("Contact@m2osw.com"));
1558 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("Contact@M2OSW.com"));
1559 :
1560 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact@m2osw:com"));
1561 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact!m2osw.com"));
1562 : }
1563 : CATCH_END_SECTION()
1564 :
1565 12 : CATCH_START_SECTION("invalid_regex_validator: Verify invalid regex character")
1566 : {
1567 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): unexpected character for a regular expression (10).");
1568 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("regex(/contact@.*\n..*/)"));
1569 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1570 1 : CATCH_REQUIRE(regex_validator == nullptr);
1571 :
1572 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): unexpected escaped character for a regular expression (13).");
1573 1 : regex_validator = advgetopt::validator::create("regex(/contact@.*\\\r..*/)");
1574 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1575 1 : CATCH_REQUIRE(regex_validator == nullptr);
1576 :
1577 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): unexpected flag character for a regular expression (57).");
1578 1 : regex_validator = advgetopt::validator::create("regex(/contact@.*..*/91)");
1579 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1580 1 : CATCH_REQUIRE(regex_validator == nullptr);
1581 :
1582 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): unexpected character for an identifier (10).");
1583 1 : regex_validator = advgetopt::validator::create("regex(not\nexpected)");
1584 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1585 1 : CATCH_REQUIRE(regex_validator == nullptr);
1586 : }
1587 : CATCH_END_SECTION()
1588 :
1589 12 : CATCH_START_SECTION("invalid_regex_validator: Verify invalid regex: missing ending /")
1590 : {
1591 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag * in regular expression \"/contact@.*\\..*\".");
1592 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag . in regular expression \"/contact@.*\\..*\".");
1593 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag . in regular expression \"/contact@.*\\..*\".");
1594 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag \\ in regular expression \"/contact@.*\\..*\".");
1595 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag * in regular expression \"/contact@.*\\..*\".");
1596 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag . in regular expression \"/contact@.*\\..*\".");
1597 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag @ in regular expression \"/contact@.*\\..*\".");
1598 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag t in regular expression \"/contact@.*\\..*\".");
1599 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag c in regular expression \"/contact@.*\\..*\".");
1600 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag a in regular expression \"/contact@.*\\..*\".");
1601 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag t in regular expression \"/contact@.*\\..*\".");
1602 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag n in regular expression \"/contact@.*\\..*\".");
1603 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag o in regular expression \"/contact@.*\\..*\".");
1604 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: unsupported regex flag c in regular expression \"/contact@.*\\..*\".");
1605 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid regex definition, ending / is missing in \"/contact@.*\\..*\".");
1606 :
1607 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("regex", {"/contact@.*\\..*"}));
1608 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1609 :
1610 1 : CATCH_REQUIRE(regex_validator != nullptr);
1611 1 : CATCH_REQUIRE(regex_validator->name() == "regex");
1612 :
1613 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("@m2osw."));
1614 1 : CATCH_REQUIRE(regex_validator->validate("contact@m2osw.com"));
1615 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("Contact@m2osw.com"));
1616 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("Contact@M2OSW.com"));
1617 :
1618 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact@m2osw:com"));
1619 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact!m2osw.com"));
1620 : }
1621 : CATCH_END_SECTION()
1622 :
1623 12 : CATCH_START_SECTION("invalid_regex_validator: Verify regex refuses more than one parameter")
1624 : {
1625 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
1626 : "error: validator_regex() only supports one parameter;"
1627 : " 2 were supplied;"
1628 : " single or double quotation may be required?");
1629 1 : advgetopt::validator::create("regex", {"[a-z]+", "[0-9]+"});
1630 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1631 :
1632 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
1633 : "error: validator_regex() only supports one parameter;"
1634 : " 2 were supplied;"
1635 : " single or double quotation may be required?");
1636 1 : advgetopt::validator::create("regex([a-z]+, [0-9]+)");
1637 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1638 :
1639 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
1640 : "error: validator_regex() only supports one parameter;"
1641 : " 3 were supplied;"
1642 : " single or double quotation may be required?");
1643 1 : advgetopt::validator::create("regex", {"[a-z]+", "[0-9]+", "[#!@]"});
1644 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1645 :
1646 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
1647 : "error: validator_regex() only supports one parameter;"
1648 : " 3 were supplied;"
1649 : " single or double quotation may be required?");
1650 1 : advgetopt::validator::create("regex(\"[a-z]+\", \"[0-9]+\", \"[#!@]\")");
1651 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1652 : }
1653 : CATCH_END_SECTION()
1654 :
1655 12 : CATCH_START_SECTION("invalid_regex_validator: Verify two regex params")
1656 : {
1657 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator_regex() only supports one parameter; 2 were supplied; single or double quotation may be required?");
1658 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("regex(/one/a, /two/b)"));
1659 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1660 :
1661 1 : CATCH_REQUIRE(regex_validator != nullptr);
1662 1 : CATCH_REQUIRE(regex_validator->name() == "regex");
1663 :
1664 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("@m2osw."));
1665 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact@m2osw.com"));
1666 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("Contact@m2osw.com"));
1667 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("Contact@M2OSW.com"));
1668 :
1669 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact@m2osw:com"));
1670 1 : CATCH_REQUIRE_FALSE(regex_validator->validate("contact!m2osw.com"));
1671 : }
1672 : CATCH_END_SECTION()
1673 :
1674 12 : CATCH_START_SECTION("invalid_regex_validator: Verify two regex params")
1675 : {
1676 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: validator(): unexpected character for an identifier (10).");
1677 2 : advgetopt::validator::pointer_t regex_validator(advgetopt::validator::create("regex('/one/'\n,'/two/b')"));
1678 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
1679 1 : CATCH_REQUIRE(regex_validator == nullptr);
1680 : }
1681 : CATCH_END_SECTION()
1682 :
1683 12 : }
1684 :
1685 :
1686 : // vim: ts=4 sw=4 et
|