Branch data Line data Source code
1 : : // Copyright 2011-2026 David Robillard <d@drobilla.net>
2 : : // SPDX-License-Identifier: ISC
3 : :
4 : : #undef NDEBUG
5 : :
6 : : #include "time_test_utils.h"
7 : :
8 : : #include <exess/exess.h>
9 : :
10 : : #include <assert.h>
11 : : #include <stdbool.h>
12 : : #include <stdint.h>
13 : : #include <string.h>
14 : :
15 : : static const ExessDay nozone = {2, EXESS_TIMEZONE_LOCAL};
16 : : static const ExessDay utc = {3, EXESS_TIMEZONE_UTC};
17 : : static const ExessDay zoned = {4, INIT_ZONE(11, 30)};
18 : : static const ExessDay lowest = {1, INIT_ZONE(-14, 0)};
19 : : static const ExessDay highest = {31, INIT_ZONE(14, 0)};
20 : : static const ExessDay garbage1 = {0, INIT_ZONE(11, 30)};
21 : : static const ExessDay garbage2 = {32, INIT_ZONE(11, 30)};
22 : :
23 : : static void
24 : 23 : check_read(const char* const string,
25 : : const ExessStatus expected_status,
26 : : const uint8_t expected_day,
27 : : const int8_t expected_tz_hour,
28 : : const int8_t expected_tz_minute,
29 : : const bool expected_tz_is_present,
30 : : const size_t expected_count)
31 : : {
32 : 23 : ExessDay value = {0, EXESS_TIMEZONE_LOCAL};
33 : :
34 : 23 : const ExessResult r = exess_read_day(string, &value);
35 [ - + ]: 23 : assert(r.status == expected_status);
36 [ - + ]: 23 : assert(r.count == expected_count);
37 [ - + ]: 23 : assert(value.day == expected_day);
38 [ + + + + : 23 : assert((!expected_tz_is_present && value.zone == EXESS_TIMEZONE_LOCAL) ||
- + ]
39 : : value.zone == (4 * expected_tz_hour) + (expected_tz_minute / 15));
40 : 23 : }
41 : :
42 : : static void
43 : 1 : test_read_day(void)
44 : : {
45 : : // No input
46 : 1 : check_read("", EXESS_EXPECTED_DASH, 0, 0, 0, false, 0);
47 : 1 : check_read("\t\n\r ", EXESS_EXPECTED_DASH, 0, 0, 0, false, 4);
48 : :
49 : : // Good values
50 : 1 : check_read("---12", EXESS_SUCCESS, 12, 0, 0, false, 5);
51 : 1 : check_read("---01", EXESS_SUCCESS, 1, 0, 0, false, 5);
52 : 1 : check_read("---12-05:00", EXESS_SUCCESS, 12, -5, 0, true, 11);
53 : 1 : check_read("---12Z", EXESS_SUCCESS, 12, 0, 0, true, 6);
54 : 1 : check_read("---26", EXESS_SUCCESS, 26, 0, 0, false, 5);
55 : 1 : check_read("---26+02:00", EXESS_SUCCESS, 26, 2, 0, true, 11);
56 : 1 : check_read("---26Z", EXESS_SUCCESS, 26, 0, 0, true, 6);
57 : 1 : check_read("---26+00:00", EXESS_SUCCESS, 26, 0, 0, true, 11);
58 : :
59 : : // Non-canonical
60 : 1 : check_read(" ---12 ", EXESS_SUCCESS, 12, 0, 0, false, 6);
61 : :
62 : : // Longest possible string
63 : 1 : check_read(
64 : : "---01-14:00", EXESS_SUCCESS, 1, -14, 0, true, EXESS_MAX_DAY_LENGTH);
65 : :
66 : : // Limits
67 : 1 : check_read("---01", EXESS_SUCCESS, 1, 0, 0, false, 5);
68 : 1 : check_read("---31", EXESS_SUCCESS, 31, 0, 0, false, 5);
69 : :
70 : : // Out of range days
71 : 1 : check_read("---00", EXESS_OUT_OF_RANGE, 0, 0, 0, false, 5);
72 : 1 : check_read("---32", EXESS_OUT_OF_RANGE, 32, 0, 0, false, 5);
73 : :
74 : : // Trailing garbage
75 : 1 : check_read("---12A", EXESS_SUCCESS, 12, 0, 0, false, 5);
76 : :
77 : : // Garbage
78 : 1 : check_read("f", EXESS_EXPECTED_DASH, 0, 0, 0, false, 0);
79 : 1 : check_read("-12", EXESS_EXPECTED_DASH, 0, 0, 0, false, 1);
80 : 1 : check_read("--12", EXESS_EXPECTED_DASH, 0, 0, 0, false, 2);
81 : 1 : check_read("---", EXESS_EXPECTED_DIGIT, 0, 0, 0, false, 3);
82 : 1 : check_read("---1", EXESS_EXPECTED_DIGIT, 1, 0, 0, false, 4);
83 : 1 : check_read("/12", EXESS_EXPECTED_DASH, 0, 0, 0, false, 0);
84 : 1 : }
85 : :
86 : : static void
87 : 12 : check_write(const ExessDay value,
88 : : const ExessStatus expected_status,
89 : : const size_t buf_size,
90 : : const char* const expected_string)
91 : : {
92 : 12 : char buf[EXESS_MAX_DATE_LENGTH + 1] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
93 : :
94 [ - + ]: 12 : assert(buf_size <= sizeof(buf));
95 : :
96 : 12 : const ExessResult r = exess_write_day(value, buf_size, buf);
97 [ - + ]: 12 : assert(r.status == expected_status);
98 [ + + ]: 12 : if (!r.status) {
99 [ - + ]: 5 : assert(!strcmp(buf, expected_string));
100 [ - + ]: 5 : assert(r.count == strlen(buf));
101 [ - + ]: 5 : assert(exess_write_day(value, 0, NULL).count == r.count);
102 : : }
103 : 12 : }
104 : :
105 : : static void
106 : 1 : test_write_day(void)
107 : : {
108 : 1 : check_write(nozone, EXESS_SUCCESS, 6, "---02");
109 : 1 : check_write(utc, EXESS_SUCCESS, 7, "---03Z");
110 : 1 : check_write(zoned, EXESS_SUCCESS, 12, "---04+11:30");
111 : 1 : check_write(lowest, EXESS_SUCCESS, 12, "---01-14:00");
112 : 1 : check_write(highest, EXESS_SUCCESS, 12, "---31+14:00");
113 : :
114 : 1 : check_write(garbage1, EXESS_BAD_VALUE, 12, "");
115 : 1 : check_write(garbage2, EXESS_BAD_VALUE, 12, "");
116 : :
117 : 1 : check_write(nozone, EXESS_NO_SPACE, 5, "");
118 : 1 : check_write(utc, EXESS_NO_SPACE, 6, "");
119 : 1 : check_write(zoned, EXESS_NO_SPACE, 11, "");
120 : 1 : check_write(lowest, EXESS_NO_SPACE, 11, "");
121 : 1 : check_write(highest, EXESS_NO_SPACE, 11, "");
122 : :
123 : : // Check that nothing is written when there isn't enough space
124 : 1 : char c = 42;
125 : 1 : const ExessResult r = exess_write_day(nozone, 0, &c);
126 [ - + ]: 1 : assert(c == 42);
127 [ - + ]: 1 : assert(r.status == EXESS_NO_SPACE);
128 [ - + ]: 1 : assert(r.count == 5);
129 : 1 : }
130 : :
131 : : int
132 : 1 : main(void)
133 : : {
134 : 1 : test_read_day();
135 : 1 : test_write_day();
136 : :
137 : 1 : return 0;
138 : : }
|