Branch data Line data Source code
1 : : // Copyright 2011-2025 David Robillard <d@drobilla.net>
2 : : // SPDX-License-Identifier: ISC
3 : :
4 : : #undef NDEBUG
5 : :
6 : : #include "int_test_utils.h"
7 : : #include "num_test_utils.h"
8 : :
9 : : #include <exess/exess.h>
10 : :
11 : : #include <assert.h>
12 : : #include <stdint.h>
13 : : #include <stdio.h>
14 : : #include <string.h>
15 : :
16 : : static void
17 : 12 : check_read(const char* const string,
18 : : const ExessStatus expected_status,
19 : : const uint32_t expected_value,
20 : : const size_t expected_count)
21 : : {
22 : 12 : uint32_t value = 0;
23 : 12 : const ExessResult r = exess_read_uint(string, &value);
24 : :
25 [ - + ]: 12 : assert(r.status == expected_status);
26 [ - + ]: 12 : assert(r.count == expected_count);
27 [ - + ]: 12 : assert(value == expected_value);
28 : 12 : }
29 : :
30 : : static void
31 : 2 : test_read_uint(void)
32 : : {
33 : : // Limits
34 : 2 : check_read("0", EXESS_SUCCESS, 0, 1);
35 : 2 : check_read("4294967295", EXESS_SUCCESS, UINT32_MAX, EXESS_MAX_UINT_LENGTH);
36 : :
37 : : // Out of range
38 : 2 : check_read("4294967296", EXESS_OUT_OF_RANGE, 0, 10);
39 : :
40 : : // Garbage
41 : 2 : check_read("E", EXESS_EXPECTED_DIGIT, 0, 0);
42 : 2 : check_read("-1", EXESS_EXPECTED_ZERO, 0, 1);
43 : 2 : check_read("+", EXESS_EXPECTED_DIGIT, 0, 1);
44 : 2 : }
45 : :
46 : : static void
47 : 6 : check_write(const uint32_t value,
48 : : const ExessStatus expected_status,
49 : : const size_t buf_size,
50 : : const char* const expected_string)
51 : : {
52 : 6 : char buf[EXESS_MAX_UINT_LENGTH + 1] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
53 : :
54 [ - + ]: 6 : assert(buf_size <= sizeof(buf));
55 : :
56 : 6 : const ExessResult r = exess_write_uint(value, buf_size, buf);
57 [ - + ]: 6 : assert(r.status == expected_status);
58 [ + + ]: 6 : if (!r.status) {
59 [ - + ]: 4 : assert(!strcmp(buf, expected_string));
60 [ - + ]: 4 : assert(r.count == strlen(buf));
61 [ - + ]: 4 : assert(exess_write_uint(value, 0, NULL).count == r.count);
62 : : }
63 : 6 : }
64 : :
65 : : static void
66 : 2 : test_write_uint(void)
67 : : {
68 : 2 : check_write(0U, EXESS_SUCCESS, 2, "0");
69 : 2 : check_write(UINT32_MAX, EXESS_SUCCESS, 11, "4294967295");
70 : 2 : check_write(UINT32_MAX, EXESS_NO_SPACE, 10, "4294967295");
71 : 2 : }
72 : :
73 : : static void
74 : 2 : test_round_trip(const ExessNumTestOptions opts)
75 : : {
76 : 2 : uint32_t parsed_value = 0;
77 : 2 : char buf[EXESS_MAX_UINT_LENGTH + 1] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
78 : :
79 [ + + ]: 2 : if (opts.exhaustive) {
80 : 1 : fprintf(stderr, "Testing xsd:unsignedInt exhaustively\n");
81 : :
82 [ + + ]: 514 : for (uint64_t i = (uint64_t)opts.low; i <= (uint64_t)opts.high; ++i) {
83 [ - + ]: 513 : assert(!exess_write_uint((uint32_t)i, sizeof(buf), buf).status);
84 [ - + ]: 513 : assert(!exess_read_uint(buf, &parsed_value).status);
85 [ - + ]: 513 : assert(parsed_value == i);
86 : :
87 : 513 : print_num_test_progress(i, UINT32_MAX);
88 : : }
89 : : } else {
90 : 1 : fprintf(
91 : 1 : stderr, "Testing xsd:unsignedInt randomly with seed %u\n", opts.seed);
92 : :
93 : 1 : uint32_t value = opts.seed;
94 [ + + ]: 16385 : for (uint64_t i = 0; i < opts.n_tests; ++i) {
95 : 16384 : value = lcg32(value);
96 : :
97 [ - + ]: 16384 : assert(!exess_write_uint(value, sizeof(buf), buf).status);
98 [ - + ]: 16384 : assert(!exess_read_uint(buf, &parsed_value).status);
99 [ - + ]: 16384 : assert(parsed_value == value);
100 : :
101 : 16384 : print_num_test_progress(i, opts.n_tests);
102 : : }
103 : : }
104 : 2 : }
105 : :
106 : : int
107 : 2 : main(int argc, char** argv)
108 : : {
109 : : const ExessNumTestOptions opts =
110 : 2 : parse_num_test_options(argc, argv, 16384U, 0U, UINT32_MAX);
111 : :
112 [ + - ]: 2 : if (!opts.error) {
113 : 2 : test_read_uint();
114 : 2 : test_write_uint();
115 : 2 : test_round_trip(opts);
116 : : }
117 : :
118 : 2 : return (int)opts.error;
119 : : }
|