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 "write_test_utils.h"
7 : :
8 : : #include <exess/exess.h>
9 : :
10 : : #include <assert.h>
11 : : #include <string.h>
12 : :
13 : : #define STRING_SIZE 26U
14 : :
15 : : static void
16 : 118 : check(const ExessDatatype datatype,
17 : : const size_t expected_read_count,
18 : : const char* const value,
19 : : const ExessStatus expected_status,
20 : : const size_t expected_write_count,
21 : : const char* const expected_string)
22 : : {
23 : 118 : char buf[STRING_SIZE] = {42};
24 : 118 : init_out_buf(sizeof(buf), buf);
25 : :
26 [ - + ]: 118 : assert(expected_write_count < sizeof(buf));
27 : :
28 : : const ExessVariableResult r =
29 : 118 : exess_write_canonical(datatype, value, expected_write_count + 1, buf);
30 : :
31 [ - + ]: 118 : assert(r.status == expected_status);
32 [ - + ]: 118 : assert(r.read_count == expected_read_count);
33 [ - + ]: 118 : assert(r.write_count == expected_write_count);
34 [ + + ]: 118 : if (expected_write_count > 0) {
35 [ - + ]: 86 : assert(expected_write_count == strlen(buf));
36 [ - + ]: 86 : assert(!strcmp(buf, expected_string));
37 : : } else {
38 [ - + ]: 32 : assert(!buf[0]);
39 : : }
40 : :
41 [ + + - + ]: 118 : assert(r.status ||
42 : : exess_write_canonical(datatype, value, 0, NULL).write_count ==
43 : : r.write_count);
44 : 118 : }
45 : :
46 : : static void
47 : 1 : test_decimal(void)
48 : : {
49 : 1 : check(EXESS_DECIMAL, 0, "", EXESS_EXPECTED_DIGIT, 0, "");
50 : 1 : check(EXESS_DECIMAL, 4, "\t\n\r ", EXESS_EXPECTED_DIGIT, 0, "");
51 : :
52 : 1 : check(EXESS_DECIMAL, 5, " -001 ", EXESS_SUCCESS, 4, "-1.0");
53 : 1 : check(EXESS_DECIMAL, 5, " -000 ", EXESS_SUCCESS, 4, "-0.0");
54 : 1 : check(EXESS_DECIMAL, 5, " 000 ", EXESS_SUCCESS, 3, "0.0");
55 : 1 : check(EXESS_DECIMAL, 5, " 001 ", EXESS_SUCCESS, 3, "1.0");
56 : 1 : check(EXESS_DECIMAL, 5, " +001 ", EXESS_SUCCESS, 3, "1.0");
57 : :
58 : 1 : check(EXESS_DECIMAL, 6, " -.123", EXESS_SUCCESS, 6, "-0.123");
59 : 1 : check(EXESS_DECIMAL, 6, " +.123", EXESS_SUCCESS, 5, "0.123");
60 : 1 : check(EXESS_DECIMAL, 3, " -0 ", EXESS_SUCCESS, 4, "-0.0");
61 : 1 : check(EXESS_DECIMAL, 3, " +0 ", EXESS_SUCCESS, 3, "0.0");
62 : :
63 : 1 : check(EXESS_DECIMAL, 7, " +00.10 ", EXESS_SUCCESS, 3, "0.1");
64 : 1 : check(EXESS_DECIMAL, 4, " +01 ", EXESS_SUCCESS, 3, "1.0");
65 : :
66 : 1 : check(EXESS_DECIMAL,
67 : : 21,
68 : : " 36893488147419103232 ",
69 : : EXESS_SUCCESS,
70 : : 22,
71 : : "36893488147419103232.0");
72 : :
73 : 1 : check(EXESS_DECIMAL,
74 : : 23,
75 : : " 0036893488147419103232 ",
76 : : EXESS_SUCCESS,
77 : : 22,
78 : : "36893488147419103232.0");
79 : :
80 : 1 : check(EXESS_DECIMAL,
81 : : 22,
82 : : " +36893488147419103232 ",
83 : : EXESS_SUCCESS,
84 : : 22,
85 : : "36893488147419103232.0");
86 : :
87 : 1 : check(EXESS_DECIMAL,
88 : : 22,
89 : : " -36893488147419103232 ",
90 : : EXESS_SUCCESS,
91 : : 23,
92 : : "-36893488147419103232.0");
93 : :
94 : 1 : check(EXESS_DECIMAL,
95 : : 24,
96 : : " +0036893488147419103232 ",
97 : : EXESS_SUCCESS,
98 : : 22,
99 : : "36893488147419103232.0");
100 : :
101 : 1 : check(EXESS_DECIMAL,
102 : : 25,
103 : : " +0036893488147419103232. ",
104 : : EXESS_SUCCESS,
105 : : 22,
106 : : "36893488147419103232.0");
107 : :
108 : 1 : check(EXESS_DECIMAL,
109 : : 27,
110 : : " +0036893488147419103232.00 ",
111 : : EXESS_SUCCESS,
112 : : 22,
113 : : "36893488147419103232.0");
114 : :
115 : 1 : check(EXESS_DECIMAL,
116 : : 30,
117 : : " +0036893488147419103232.12300 ",
118 : : EXESS_SUCCESS,
119 : : 24,
120 : : "36893488147419103232.123");
121 : :
122 : 1 : check(EXESS_DECIMAL,
123 : : 24,
124 : : " -0036893488147419103232 ",
125 : : EXESS_SUCCESS,
126 : : 23,
127 : : "-36893488147419103232.0");
128 : :
129 : 1 : check(EXESS_DECIMAL,
130 : : 25,
131 : : " -0036893488147419103232. ",
132 : : EXESS_SUCCESS,
133 : : 23,
134 : : "-36893488147419103232.0");
135 : :
136 : 1 : check(EXESS_DECIMAL,
137 : : 27,
138 : : " -0036893488147419103232.00 ",
139 : : EXESS_SUCCESS,
140 : : 23,
141 : : "-36893488147419103232.0");
142 : :
143 : 1 : check(EXESS_DECIMAL,
144 : : 30,
145 : : " -0036893488147419103232.12300 ",
146 : : EXESS_SUCCESS,
147 : : 25,
148 : : "-36893488147419103232.123");
149 : :
150 : 1 : check(EXESS_DECIMAL, 6, " -1234extra", EXESS_SUCCESS, 7, "-1234.0");
151 : 1 : check(EXESS_DECIMAL, 5, " 1234extra", EXESS_SUCCESS, 6, "1234.0");
152 : :
153 : 1 : check(EXESS_DECIMAL, 1, " f", EXESS_EXPECTED_DIGIT, 0, "");
154 : 1 : check(EXESS_DECIMAL, 0, "", EXESS_EXPECTED_DIGIT, 0, "");
155 : 1 : }
156 : :
157 : : static void
158 : 1 : test_integer(void)
159 : : {
160 : 1 : check(EXESS_INTEGER, 0, "", EXESS_EXPECTED_DIGIT, 0, "");
161 : 1 : check(EXESS_INTEGER, 4, "\t\n\r ", EXESS_EXPECTED_DIGIT, 0, "");
162 : :
163 : : // Integer
164 : :
165 : 1 : check(EXESS_INTEGER, 5, " -001 ", EXESS_SUCCESS, 2, "-1");
166 : 1 : check(EXESS_INTEGER, 5, " 000 ", EXESS_SUCCESS, 1, "0");
167 : 1 : check(EXESS_INTEGER, 5, " 001 ", EXESS_SUCCESS, 1, "1");
168 : 1 : check(EXESS_INTEGER, 5, " +001 ", EXESS_SUCCESS, 1, "1");
169 : :
170 : 1 : check(EXESS_INTEGER, 1, " junk 987654321 ", EXESS_EXPECTED_DIGIT, 0, "");
171 : 1 : check(EXESS_INTEGER, 10, " 987654321 junk ", EXESS_SUCCESS, 9, "987654321");
172 : :
173 : 1 : check(EXESS_INTEGER,
174 : : 21,
175 : : " 36893488147419103232 ",
176 : : EXESS_SUCCESS,
177 : : 20,
178 : : "36893488147419103232");
179 : :
180 : 1 : check(EXESS_INTEGER,
181 : : 23,
182 : : " 0036893488147419103232 ",
183 : : EXESS_SUCCESS,
184 : : 20,
185 : : "36893488147419103232");
186 : :
187 : 1 : check(EXESS_INTEGER,
188 : : 22,
189 : : " +36893488147419103232 ",
190 : : EXESS_SUCCESS,
191 : : 20,
192 : : "36893488147419103232");
193 : :
194 : 1 : check(EXESS_INTEGER,
195 : : 24,
196 : : " +0036893488147419103232 ",
197 : : EXESS_SUCCESS,
198 : : 20,
199 : : "36893488147419103232");
200 : :
201 : 1 : check(EXESS_INTEGER,
202 : : 22,
203 : : " -36893488147419103232 ",
204 : : EXESS_SUCCESS,
205 : : 21,
206 : : "-36893488147419103232");
207 : :
208 : 1 : check(EXESS_INTEGER,
209 : : 24,
210 : : " -0036893488147419103232 ",
211 : : EXESS_SUCCESS,
212 : : 21,
213 : : "-36893488147419103232");
214 : :
215 : : // NonPositiveInteger
216 : :
217 : 1 : check(EXESS_NON_POSITIVE_INTEGER, 2, " 0 ", EXESS_SUCCESS, 1, "0");
218 : 1 : check(EXESS_NON_POSITIVE_INTEGER, 5, " -001 ", EXESS_SUCCESS, 2, "-1");
219 : 1 : check(EXESS_NON_POSITIVE_INTEGER, 5, " 000 ", EXESS_SUCCESS, 1, "0");
220 : 1 : check(EXESS_NON_POSITIVE_INTEGER, 4, " 001 ", EXESS_BAD_VALUE, 0, "");
221 : 1 : check(EXESS_NON_POSITIVE_INTEGER, 1, " +001 ", EXESS_BAD_VALUE, 0, "");
222 : :
223 : 1 : check(EXESS_NON_POSITIVE_INTEGER,
224 : : 22,
225 : : " -36893488147419103232 ",
226 : : EXESS_SUCCESS,
227 : : 21,
228 : : "-36893488147419103232");
229 : :
230 : 1 : check(EXESS_NON_POSITIVE_INTEGER,
231 : : 24,
232 : : " -0036893488147419103232 ",
233 : : EXESS_SUCCESS,
234 : : 21,
235 : : "-36893488147419103232");
236 : :
237 : : // NegativeInteger
238 : :
239 : 1 : check(EXESS_NEGATIVE_INTEGER, 1, " 0 ", EXESS_BAD_VALUE, 0, "");
240 : 1 : check(EXESS_NEGATIVE_INTEGER, 5, " -001 ", EXESS_SUCCESS, 2, "-1");
241 : 1 : check(EXESS_NEGATIVE_INTEGER, 2, " 000 ", EXESS_BAD_VALUE, 0, "");
242 : 1 : check(EXESS_NEGATIVE_INTEGER, 2, " 001 ", EXESS_BAD_VALUE, 0, "");
243 : 1 : check(EXESS_NEGATIVE_INTEGER, 1, " +001 ", EXESS_BAD_VALUE, 0, "");
244 : :
245 : 1 : check(EXESS_NEGATIVE_INTEGER,
246 : : 22,
247 : : " -36893488147419103232 ",
248 : : EXESS_SUCCESS,
249 : : 21,
250 : : "-36893488147419103232");
251 : :
252 : 1 : check(EXESS_NEGATIVE_INTEGER,
253 : : 24,
254 : : " -0036893488147419103232 ",
255 : : EXESS_SUCCESS,
256 : : 21,
257 : : "-36893488147419103232");
258 : :
259 : : // NonNegativeInteger
260 : :
261 : 1 : check(EXESS_NON_NEGATIVE_INTEGER, 2, " 0 ", EXESS_SUCCESS, 1, "0");
262 : 1 : check(EXESS_NON_NEGATIVE_INTEGER, 1, " -001 ", EXESS_BAD_VALUE, 0, "");
263 : 1 : check(EXESS_NON_NEGATIVE_INTEGER, 5, " 000 ", EXESS_SUCCESS, 1, "0");
264 : 1 : check(EXESS_NON_NEGATIVE_INTEGER, 5, " 001 ", EXESS_SUCCESS, 1, "1");
265 : 1 : check(EXESS_NON_NEGATIVE_INTEGER, 5, " +001 ", EXESS_SUCCESS, 1, "1");
266 : :
267 : 1 : check(EXESS_NON_NEGATIVE_INTEGER,
268 : : 21,
269 : : " 36893488147419103232 ",
270 : : EXESS_SUCCESS,
271 : : 20,
272 : : "36893488147419103232");
273 : :
274 : 1 : check(EXESS_NON_NEGATIVE_INTEGER,
275 : : 23,
276 : : " 0036893488147419103232 ",
277 : : EXESS_SUCCESS,
278 : : 20,
279 : : "36893488147419103232");
280 : :
281 : : // PositiveInteger
282 : :
283 : 1 : check(EXESS_POSITIVE_INTEGER, 1, " 0 ", EXESS_BAD_VALUE, 0, "");
284 : 1 : check(EXESS_POSITIVE_INTEGER, 1, " -001 ", EXESS_BAD_VALUE, 0, "");
285 : 1 : check(EXESS_POSITIVE_INTEGER, 2, " 000 ", EXESS_BAD_VALUE, 0, "");
286 : 1 : check(EXESS_POSITIVE_INTEGER, 5, " 001 ", EXESS_SUCCESS, 1, "1");
287 : 1 : check(EXESS_POSITIVE_INTEGER, 5, " +001 ", EXESS_SUCCESS, 1, "1");
288 : :
289 : 1 : check(EXESS_POSITIVE_INTEGER,
290 : : 21,
291 : : " 36893488147419103232 ",
292 : : EXESS_SUCCESS,
293 : : 20,
294 : : "36893488147419103232");
295 : :
296 : 1 : check(EXESS_POSITIVE_INTEGER,
297 : : 23,
298 : : " 0036893488147419103232 ",
299 : : EXESS_SUCCESS,
300 : : 20,
301 : : "36893488147419103232");
302 : 1 : }
303 : :
304 : : static void
305 : 1 : test_fixed_numbers(void)
306 : : {
307 : 1 : check(EXESS_DOUBLE, 7, " +00.10 ", EXESS_SUCCESS, 6, "1.0E-1");
308 : 1 : check(EXESS_FLOAT, 7, " +00.10 ", EXESS_SUCCESS, 13, "1.00000001E-1");
309 : 1 : check(EXESS_BOOLEAN, 2, " 0 ", EXESS_SUCCESS, 5, "false");
310 : 1 : check(EXESS_BOOLEAN, 2, " 1 ", EXESS_SUCCESS, 4, "true");
311 : 1 : check(EXESS_LONG, 5, " +012 ", EXESS_SUCCESS, 2, "12");
312 : 1 : check(EXESS_INT, 5, " +012 ", EXESS_SUCCESS, 2, "12");
313 : 1 : check(EXESS_SHORT, 5, " +012 ", EXESS_SUCCESS, 2, "12");
314 : 1 : check(EXESS_BYTE, 5, " +012 ", EXESS_SUCCESS, 2, "12");
315 : 1 : check(EXESS_ULONG, 4, " 012 ", EXESS_SUCCESS, 2, "12");
316 : 1 : check(EXESS_UINT, 4, " 012 ", EXESS_SUCCESS, 2, "12");
317 : 1 : check(EXESS_USHORT, 4, " 012 ", EXESS_SUCCESS, 2, "12");
318 : 1 : check(EXESS_UBYTE, 4, " 012 ", EXESS_SUCCESS, 2, "12");
319 : :
320 : 1 : check(EXESS_BOOLEAN, 0, "X", EXESS_EXPECTED_BOOLEAN, 0, "");
321 : 1 : check(EXESS_FLOAT, 0, "X", EXESS_EXPECTED_DIGIT, 0, "");
322 : 1 : check(EXESS_DOUBLE, 0, "X", EXESS_EXPECTED_DIGIT, 0, "");
323 : 1 : }
324 : :
325 : : static void
326 : 1 : test_time(void)
327 : : {
328 : 1 : check(EXESS_DURATION, 6, " P0Y6M ", EXESS_SUCCESS, 3, "P6M");
329 : 1 : check(EXESS_DURATION, 8, " P1Y6M0D ", EXESS_SUCCESS, 5, "P1Y6M");
330 : 1 : check(EXESS_TIME, 15, " 12:15:01+00:00 ", EXESS_SUCCESS, 9, "12:15:01Z");
331 : 1 : check(EXESS_TIME, 9, " 24:00:00 ", EXESS_SUCCESS, 8, "00:00:00");
332 : 1 : check(EXESS_TIME, 10, " 24:00:00Z ", EXESS_SUCCESS, 9, "00:00:00Z");
333 : 1 : check(
334 : : EXESS_TIME, 15, " 24:00:00+02:00 ", EXESS_SUCCESS, 14, "00:00:00+02:00");
335 : 1 : check(
336 : : EXESS_DATE, 18, " 02004-04-12+00:00 ", EXESS_SUCCESS, 11, "2004-04-12Z");
337 : 1 : }
338 : :
339 : : static void
340 : 1 : test_date_time(void)
341 : : {
342 : : // Read error
343 : 1 : check(EXESS_DATE_TIME, 2, "99-01-01T12:00:00", EXESS_EXPECTED_DIGIT, 0, "");
344 : :
345 : : // Integer seconds
346 : 1 : check(EXESS_DATE_TIME,
347 : : 26,
348 : : " 02001-02-03T04:05:06.0000 ",
349 : : EXESS_SUCCESS,
350 : : 19,
351 : : "2001-02-03T04:05:06");
352 : :
353 : : // Local
354 : 1 : check(EXESS_DATE_TIME,
355 : : 25,
356 : : " 02001-02-03T04:05:06.007 ",
357 : : EXESS_SUCCESS,
358 : : 23,
359 : : "2001-02-03T04:05:06.007");
360 : :
361 : : // UTC
362 : 1 : check(EXESS_DATE_TIME,
363 : : 22,
364 : : " 02001-02-03T04:46:59Z ",
365 : : EXESS_SUCCESS,
366 : : 20,
367 : : "2001-02-03T04:46:59Z");
368 : :
369 : : // UTC redundant negative zero form
370 : 1 : check(EXESS_DATE_TIME,
371 : : 27,
372 : : " 02001-02-03T04:46:59-00:00 ",
373 : : EXESS_SUCCESS,
374 : : 20,
375 : : "2001-02-03T04:46:59Z");
376 : :
377 : : // UTC redundant positive zero form
378 : 1 : check(EXESS_DATE_TIME,
379 : : 27,
380 : : " 02001-02-03T04:46:59+00:00 ",
381 : : EXESS_SUCCESS,
382 : : 20,
383 : : "2001-02-03T04:46:59Z");
384 : :
385 : : // Midnight at end of day
386 : 1 : check(EXESS_DATE_TIME,
387 : : 27,
388 : : " 02001-02-03T24:00:00+00:00 ",
389 : : EXESS_SUCCESS,
390 : : 20,
391 : : "2001-02-04T00:00:00Z");
392 : :
393 : : // Midnight at end of February in a normal year
394 : 1 : check(EXESS_DATE_TIME,
395 : : 27,
396 : : " 02001-02-28T24:00:00+00:00 ",
397 : : EXESS_SUCCESS,
398 : : 20,
399 : : "2001-03-01T00:00:00Z");
400 : :
401 : : // Midnight at end of the second last day of February in a leap year
402 : 1 : check(EXESS_DATE_TIME,
403 : : 27,
404 : : " 02000-02-28T24:00:00+00:00 ",
405 : : EXESS_SUCCESS,
406 : : 20,
407 : : "2000-02-29T00:00:00Z");
408 : :
409 : : // Midnight at end February in a leap year
410 : 1 : check(EXESS_DATE_TIME,
411 : : 27,
412 : : " 02000-02-29T24:00:00+00:00 ",
413 : : EXESS_SUCCESS,
414 : : 20,
415 : : "2000-03-01T00:00:00Z");
416 : :
417 : : // Happy new year!
418 : 1 : check(EXESS_DATE_TIME,
419 : : 27,
420 : : " 02001-12-31T24:00:00+00:00 ",
421 : : EXESS_SUCCESS,
422 : : 20,
423 : : "2002-01-01T00:00:00Z");
424 : 1 : }
425 : :
426 : : static void
427 : 1 : test_binary(void)
428 : : {
429 : 1 : check(EXESS_HEX, 8, "DEADB33F", EXESS_SUCCESS, 8, "DEADB33F");
430 : 1 : check(EXESS_HEX, 12, "\t\n\r DEADB33F", EXESS_SUCCESS, 8, "DEADB33F");
431 : 1 : check(EXESS_HEX, 2, " D EA D B3 3F", EXESS_EXPECTED_HEX, 0, NULL);
432 : 1 : check(EXESS_HEX, 0, "invalid", EXESS_EXPECTED_HEX, 0, NULL);
433 : 1 : check(EXESS_HEX, 5, "1A2B3", EXESS_EXPECTED_HEX, 0, NULL);
434 : 1 : check(EXESS_HEX, 1, "1", EXESS_EXPECTED_HEX, 0, NULL);
435 : 1 : check(EXESS_HEX, 0, "", EXESS_EXPECTED_HEX, 0, NULL);
436 : :
437 : 1 : check(EXESS_BASE64, 14, "\tZ\nm\r9 v\tY\nmFy", EXESS_SUCCESS, 8, "Zm9vYmFy");
438 : 1 : check(EXESS_BASE64, 0, "!nvalid", EXESS_EXPECTED_BASE64, 0, "");
439 : 1 : check(EXESS_BASE64, 1, "Z", EXESS_EXPECTED_BASE64, 0, "");
440 : 1 : check(EXESS_BASE64, 2, "Zm", EXESS_EXPECTED_BASE64, 0, "");
441 : 1 : check(EXESS_BASE64, 3, "Zm9", EXESS_EXPECTED_BASE64, 0, "");
442 : 1 : check(EXESS_BASE64, 0, "", EXESS_EXPECTED_BASE64, 0, "");
443 : 1 : }
444 : :
445 : : int
446 : 1 : main(void)
447 : : {
448 : 1 : check(EXESS_NOTHING, 0, "?", EXESS_UNSUPPORTED, 0, "");
449 : :
450 : 1 : test_decimal();
451 : 1 : test_integer();
452 : 1 : test_fixed_numbers();
453 : 1 : test_time();
454 : 1 : test_date_time();
455 : 1 : test_binary();
456 : :
457 : 1 : return 0;
458 : : }
|