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