1 /* -*- coding: utf-8 -*-
2 * ----------------------------------------------------------------------
3 * Copyright © 2011-2014, RedJack, LLC.
4 * All rights reserved.
5 *
6 * Please see the COPYING file in this distribution for license details.
7 * ----------------------------------------------------------------------
8 */
9
10 #include <errno.h>
11 #include <stdarg.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 #include <check.h>
17
18 #include "libcork/config.h"
19 #include "libcork/core/byte-order.h"
20 #include "libcork/core/error.h"
21 #include "libcork/core/hash.h"
22 #include "libcork/core/id.h"
23 #include "libcork/core/net-addresses.h"
24 #include "libcork/core/timestamp.h"
25 #include "libcork/core/types.h"
26 #include "libcork/core/u128.h"
27 #include "libcork/os/subprocess.h"
28
29 #include "helpers.h"
30
31
32 /*-----------------------------------------------------------------------
33 * Core types
34 */
35
START_TEST(test_bool)36 START_TEST(test_bool)
37 {
38 bool value;
39
40 value = true;
41 fail_unless(value, "Unexpected true value");
42
43 value = false;
44 fail_if(value, "Unexpected false value");
45 }
46 END_TEST
47
START_TEST(test_int_types)48 START_TEST(test_int_types)
49 {
50 /*
51 * Make sure we have all of the C99 fixed-size integer types
52 * available.
53 */
54
55 #define TEST_INT_TYPE(type) \
56 { \
57 type i = 0; \
58 fail_unless(i == 0, "Unexpected value for " #type); \
59 }
60
61 TEST_INT_TYPE(int8_t);
62 TEST_INT_TYPE(int16_t);
63 TEST_INT_TYPE(int32_t);
64 TEST_INT_TYPE(int64_t);
65 TEST_INT_TYPE(uint8_t);
66 TEST_INT_TYPE(uint16_t);
67 TEST_INT_TYPE(uint32_t);
68 TEST_INT_TYPE(uint64_t);
69 TEST_INT_TYPE(size_t);
70 TEST_INT_TYPE(ptrdiff_t);
71 TEST_INT_TYPE(intptr_t);
72 TEST_INT_TYPE(uintptr_t);
73
74 #undef TEST_INT_TYPE
75 }
76 END_TEST
77
78
START_TEST(test_int_sizeof)79 START_TEST(test_int_sizeof)
80 {
81 /*
82 * Test that our CORK_SIZEOF_FOO preprocessor macros match the
83 * results of the builtin sizeof operator.
84 */
85
86 #define TEST_SIZEOF(TYPE, type) \
87 { \
88 fail_unless(CORK_SIZEOF_##TYPE == sizeof(type), \
89 "Incorrect size for " #type ": got %zu, expected %zu", \
90 (size_t) CORK_SIZEOF_##TYPE, \
91 (size_t) sizeof(type)); \
92 }
93
94 TEST_SIZEOF(SHORT, short)
95 TEST_SIZEOF(SHORT, unsigned short)
96 TEST_SIZEOF(INT, int)
97 TEST_SIZEOF(INT, unsigned int)
98 TEST_SIZEOF(LONG, long)
99 TEST_SIZEOF(LONG, unsigned long)
100 TEST_SIZEOF(POINTER, void *)
101 TEST_SIZEOF(POINTER, int *)
102 TEST_SIZEOF(POINTER, void (*)(void))
103
104 #undef TEST_SIZEOF
105 }
106 END_TEST
107
108
109 /*-----------------------------------------------------------------------
110 * Strings
111 */
112
113 static void
test_strndup(const char * string,size_t size)114 test_strndup(const char *string, size_t size)
115 {
116 const char *copy;
117
118 copy = cork_strndup(string, size);
119 if (memcmp(string, copy, size) != 0) {
120 fail("cork_strndup failed");
121 }
122 cork_strfree(copy);
123
124 copy = cork_xstrndup(string, size);
125 fail_if(copy == NULL, "cork_xstrndup couldn't allocate copy");
126 if (memcmp(string, copy, size) != 0) {
127 fail("cork_xstrndup failed");
128 }
129 cork_strfree(copy);
130 }
131
START_TEST(test_string)132 START_TEST(test_string)
133 {
134 DESCRIBE_TEST;
135 test_strndup("", 0);
136 test_strndup("abc", 3);
137 test_strndup("abc\x00xyz", 7);
138 }
139 END_TEST
140
141
142 /*-----------------------------------------------------------------------
143 * Endianness
144 */
145
START_TEST(test_endianness)146 START_TEST(test_endianness)
147 {
148 #define TEST_ENDIAN(TYPE, type, sz, expected, ...) \
149 { \
150 union { uint8_t octets[sz]; type val; } u = \
151 { { __VA_ARGS__ } }; \
152 \
153 type from_big = CORK_##TYPE##_BIG_TO_HOST(u.val); \
154 fail_unless(from_big == expected, \
155 "Unexpected big-to-host " #type " value"); \
156 \
157 type from_big_in_place = u.val; \
158 CORK_##TYPE##_BIG_TO_HOST_IN_PLACE(from_big_in_place); \
159 fail_unless(from_big_in_place == expected, \
160 "Unexpected in-place big-to-host " #type " value"); \
161 \
162 type to_big = CORK_##TYPE##_HOST_TO_BIG(expected); \
163 fail_unless(to_big == u.val, \
164 "Unexpected host-to-big " #type " value"); \
165 \
166 type to_big_in_place = expected; \
167 CORK_##TYPE##_HOST_TO_BIG_IN_PLACE(to_big_in_place); \
168 fail_unless(to_big_in_place == u.val, \
169 "Unexpected in-place host-to-big " #type " value"); \
170 \
171 int i; \
172 for (i = 0; i < sz/2; i++) { \
173 uint8_t tmp = u.octets[i]; \
174 u.octets[i] = u.octets[sz-i-1]; \
175 u.octets[sz-i-1] = tmp; \
176 } \
177 \
178 type from_little = CORK_##TYPE##_LITTLE_TO_HOST(u.val); \
179 fail_unless(from_little == expected, \
180 "Unexpected little-to-host " #type " value"); \
181 \
182 type from_little_in_place = u.val; \
183 CORK_##TYPE##_LITTLE_TO_HOST_IN_PLACE(from_little_in_place); \
184 fail_unless(from_little_in_place == expected, \
185 "Unexpected in-place little-to-host " #type " value"); \
186 \
187 type to_little = CORK_##TYPE##_HOST_TO_LITTLE(expected); \
188 fail_unless(to_little == u.val, \
189 "Unexpected host-to-little " #type " value"); \
190 \
191 type to_little_in_place = expected; \
192 CORK_##TYPE##_HOST_TO_LITTLE_IN_PLACE(to_little_in_place); \
193 fail_unless(to_little_in_place == u.val, \
194 "Unexpected in-place host-to-little " #type " value"); \
195 }
196
197 TEST_ENDIAN(UINT16, uint16_t, 2, 0x0102, 1, 2);
198 TEST_ENDIAN(UINT32, uint32_t, 4, 0x01020304, 1, 2, 3, 4);
199 TEST_ENDIAN(UINT64, uint64_t, 8, UINT64_C(0x0102030405060708),
200 1, 2, 3, 4, 5, 6, 7, 8);
201
202 #undef TEST_ENDIAN
203 }
204 END_TEST
205
206
207 /*-----------------------------------------------------------------------
208 * Built-in errors
209 */
210
START_TEST(test_error_prefix)211 START_TEST(test_error_prefix)
212 {
213 DESCRIBE_TEST;
214 cork_error_clear();
215 cork_error_set_printf
216 (CORK_UNKNOWN_ERROR, "%u errors occurred", (unsigned int) 17);
217 fail_unless_streq("Error messages",
218 "17 errors occurred",
219 cork_error_message());
220 cork_error_prefix("The %s is aborting because ", "program");
221 fail_unless_streq("Error messages",
222 "The program is aborting because 17 errors occurred",
223 cork_error_message());
224 cork_error_clear();
225 }
226 END_TEST
227
START_TEST(test_system_error)228 START_TEST(test_system_error)
229 {
230 DESCRIBE_TEST;
231 /* Artificially flag a system error and make sure we can detect it */
232 errno = ENOMEM;
233 cork_error_clear();
234 cork_system_error_set();
235 fail_unless(cork_error_code() == ENOMEM,
236 "Expected a system error");
237 printf("Got error: %s\n", cork_error_message());
238 cork_error_clear();
239 }
240 END_TEST
241
242
243 /*-----------------------------------------------------------------------
244 * Hash values
245 */
246
247 #define test_hash_func(func, expected, ...) \
248 fail_unless(func(0, __VA_ARGS__) == expected, \
249 "Unexpected hash value 0x%08" PRIx32 \
250 " (expected 0x%08" PRIx32 ")", \
251 func(0, __VA_ARGS__), expected);
252
253 #if CORK_HOST_ENDIANNESS == CORK_LITTLE_ENDIAN
254 #if CORK_SIZEOF_POINTER == 8
255 #define test_hash_buf(buf, len, little32, big32, little64, big64) \
256 test_hash_func(cork_hash_buffer, little64, buf, len)
257 #define test_hash_var(var, little32, big32, little64, big64) \
258 test_hash_func(cork_hash_variable, little64, var)
259 #else
260 #define test_hash_buf(buf, len, little32, big32, little64, big64) \
261 test_hash_func(cork_hash_buffer, little32, buf, len)
262 #define test_hash_var(var, little32, big32, little64, big64) \
263 test_hash_func(cork_hash_variable, little32, var)
264 #endif
265 #else
266 #if CORK_SIZEOF_POINTER == 8
267 #define test_hash_buf(buf, len, little32, big32, little64, big64) \
268 test_hash_func(cork_hash_buffer, big64, buf, len)
269 #define test_hash_var(var, little32, big32, little64, big64) \
270 test_hash_func(cork_hash_variable, big64, var)
271 #else
272 #define test_hash_buf(buf, len, little32, big32, little64, big64) \
273 test_hash_func(cork_hash_buffer, big32, buf, len)
274 #define test_hash_var(var, little32, big32, little64, big64) \
275 test_hash_func(cork_hash_variable, big32, var)
276 #endif
277 #endif
278
279
280 #define test_stable_hash_buf(buf, len, expected) \
281 test_hash_func(cork_stable_hash_buffer, expected, buf, len)
282 #define test_stable_hash_var(var, expected) \
283 test_hash_func(cork_stable_hash_variable, expected, var)
284
285
286 #define test_big_hash_func(buf, len, e1, e2) \
287 do { \
288 cork_big_hash seed = CORK_BIG_HASH_INIT(); \
289 cork_big_hash expected = {cork_u128_from_64(e1, e2)}; \
290 cork_big_hash actual = cork_big_hash_buffer(seed, buf, len); \
291 fail_unless(cork_big_hash_equal(actual, expected), \
292 "\nUnexpected hash value 0x%016" PRIx64 ".%016" PRIx64 \
293 "\n (expected 0x%016" PRIx64 ".%016" PRIx64 ")", \
294 cork_u128_be64(actual.u128, 0), \
295 cork_u128_be64(actual.u128, 1), \
296 cork_u128_be64(expected.u128, 0), \
297 cork_u128_be64(expected.u128, 1)); \
298 } while (0)
299
300 #if CORK_HOST_ENDIANNESS == CORK_LITTLE_ENDIAN
301 #if CORK_SIZEOF_POINTER == 8
302 #define test_big_hash_buf(buf,len,l32a,l32b,b32a,b32b,l64a,l64b,b64a,b64b) \
303 test_big_hash_func(buf, len, l64a, l64b)
304 #else
305 #define test_big_hash_buf(buf,len,l32a,l32b,b32a,b32b,l64a,l64b,b64a,b64b) \
306 test_big_hash_func(buf, len, l32a, l32b)
307 #endif
308 #else
309 #if CORK_SIZEOF_POINTER == 8
310 #define test_big_hash_buf(buf,len,l32a,l32b,b32a,b32b,l64a,l64b,b64a,b64b) \
311 test_big_hash_func(buf, len, b64a, b64b)
312 #else
313 #define test_big_hash_buf(buf,len,l32a,l32b,b32a,b32b,l64a,l64b,b64a,b64b) \
314 test_big_hash_func(buf, len, b32a, b32b)
315 #endif
316 #endif
317
318
START_TEST(test_hash)319 START_TEST(test_hash)
320 {
321 DESCRIBE_TEST;
322
323 static const char BUF[] = "test";
324 static size_t LEN = sizeof(BUF);
325 static const char LONG_BUF[] =
326 "this is a much longer test string in the hopes that we have to "
327 "go through a few iterations of the hashing loop in order to "
328 "calculate the value of the hash which we are trying to compute.";
329 static size_t LONG_LEN = sizeof(LONG_BUF);
330 uint32_t val32 = 1234;
331 uint64_t val64 = 1234;
332 uint32_t stable_val32 = CORK_UINT32_HOST_TO_LITTLE(1234);
333 uint64_t stable_val64 = CORK_UINT64_HOST_TO_LITTLE(1234);
334
335 /* without the NUL terminator */
336 test_stable_hash_buf(BUF, LEN-1, 0xba6bd213);
337 test_hash_buf(BUF, LEN-1,
338 /* little 32 */ 0xba6bd213,
339 /* big 32 */ 0x29d175e5,
340 /* little 64 */ 0xac7d28cc,
341 /* big 64 */ 0x74bde19d);
342 test_big_hash_buf(BUF, LEN-1,
343 /* little 32 */ 0x6f02ef30550c7d68LL, 0x550c7d68550c7d68LL,
344 /* big 32 */ 0x6f02ef30550c7d68LL, 0x550c7d68550c7d68LL,
345 /* little 64 */ 0xac7d28cc74bde19dLL, 0x9a128231f9bd4d82LL,
346 /* big 64 */ 0xac7d28cc74bde19dLL, 0x9a128231f9bd4d82LL);
347
348 /* with the NUL terminator */
349 test_stable_hash_buf(BUF, LEN, 0x586fce33);
350 test_hash_buf(BUF, LEN,
351 /* little 32 */ 0x586fce33,
352 /* big 32 */ 0xe31d1ce0,
353 /* little 64 */ 0xc3812fdf,
354 /* big 64 */ 0x4d18f852);
355 test_big_hash_buf(BUF, LEN,
356 /* little 32 */ 0x98c2b52b29ab177cLL, 0x29ab177c29ab177cLL,
357 /* big 32 */ 0x98c2b52b29ab177cLL, 0x29ab177c29ab177cLL,
358 /* little 64 */ 0xc3812fdf4d18f852LL, 0xc81a9057aa737aecLL,
359 /* big 64 */ 0xc3812fdf4d18f852LL, 0xc81a9057aa737aecLL);
360
361 /* without the NUL terminator */
362 test_stable_hash_buf(LONG_BUF, LONG_LEN-1, 0x5caacc30);
363 test_hash_buf(LONG_BUF, LONG_LEN-1,
364 /* little 32 */ 0x5caacc30,
365 /* big 32 */ 0x88f94165,
366 /* little 64 */ 0xcbdc2092,
367 /* big 64 */ 0x03578c96);
368 test_big_hash_buf(LONG_BUF, LONG_LEN-1,
369 /* little 32 */ 0x4240d5134fb7793cLL, 0xee7e281c799f335aLL,
370 /* big 32 */ 0xab564a5e029c92a4LL, 0x0bd80c741093400fLL,
371 /* little 64 */ 0xcbdc20928fa72e9cLL, 0x48de52d2c680420eLL,
372 /* big 64 */ 0x5935f90a03578c96LL, 0x163e514fff9c30a8LL);
373
374 /* with the NUL terminator */
375 test_stable_hash_buf(LONG_BUF, LONG_LEN, 0x5e37d33d);
376 test_hash_buf(LONG_BUF, LONG_LEN,
377 /* little 32 */ 0x5e37d33d,
378 /* big 32 */ 0x4977421a,
379 /* little 64 */ 0xe89ec005,
380 /* big 64 */ 0x8c919559);
381 test_big_hash_buf(LONG_BUF, LONG_LEN,
382 /* little 32 */ 0x63bcdcd0c2615146LL, 0x8e7fd7aaece3cab6LL,
383 /* big 32 */ 0x250b47cda3fc07fdLL, 0x840c4bb606aafbd0LL,
384 /* little 64 */ 0xe89ec0054becb434LL, 0x826391b83f0b4d3eLL,
385 /* big 64 */ 0xf00a12ab8c919559LL, 0x684ecf4973c66eacLL);
386
387 test_stable_hash_var(stable_val32, 0x6bb65380);
388 test_hash_var(val32,
389 /* little 32 */ 0x6bb65380,
390 /* big 32 */ 0x6bb65380,
391 /* little 64 */ 0x061fecc8,
392 /* big 64 */ 0x7e1b3998);
393
394 test_stable_hash_var(stable_val64, 0x4d5c4063);
395 test_hash_var(val64,
396 /* little 32 */ 0x4d5c4063,
397 /* big 32 */ 0xbaeee6e9,
398 /* little 64 */ 0xb119ee69,
399 /* big 64 */ 0x267305fb);
400 }
401 END_TEST
402
403
404 /*-----------------------------------------------------------------------
405 * IP addresses
406 */
407
408 #define IPV4_TESTS(good, bad) \
409 good("192.168.1.100", "192.168.1.100"); \
410 good("01.002.0003.00000004", "1.2.3.4"); \
411 good("010.0020.00034.00000089", "10.20.34.89"); \
412 good("0100.000200.00.000", "100.200.0.0"); \
413 bad("", -1); \
414 bad(".", -1); \
415 bad("192.168.0.", -1); \
416 bad("192.168.0.1.", -1); \
417 bad("192..168.0.1", -1); \
418 bad("192.168.0.1.2", -1); \
419 bad(".168.0.1.2", -1); \
420 bad("256.0.0.0", -1); \
421 bad("00256.0.0.0", -1); \
422 bad("392.0.0.0", -1); \
423 bad("1920.0.0.0", -1); \
424 bad("stuv", -1); \
425
426 #define IPV6_TESTS(good, bad) \
427 good("::", "::"); \
428 good("0:0:0:0:0:0:0:0", "::"); \
429 good("0000:0000:0000:0000:0000:0000:0000:0000", "::"); \
430 good("fe80::", "fe80::"); \
431 good("fe80:0:0:0:0:0:0:0", "fe80::"); \
432 good("fe80:0000:0000:0000:0000:0000:0000:0000", "fe80::"); \
433 good("::1", "::1"); \
434 good("0:0:0:0:0:0:0:1", "::1"); \
435 good("0000:0000:0000:0000:0000:0000:0000:0001", "::1"); \
436 good("fe80::1", "fe80::1"); \
437 good("fe80:0:0:0:0:0:0:1", "fe80::1"); \
438 good("fe80:0000:0000:0000:0000:0000:0000:0001", "fe80::1"); \
439 good("0:1:2:3:4:5:6:7", "0:1:2:3:4:5:6:7"); \
440 good("1230:4567:89ab:cdef:1230:4567:89ab:cdef", \
441 "1230:4567:89ab:cdef:1230:4567:89ab:cdef"); \
442 good("::ffff:192.168.1.100", "::ffff:192.168.1.100"); \
443 bad("", -1); \
444 bad(":", -1); \
445 bad("fe80:", -1); \
446 bad("fe80::1::2", -1); \
447 bad("1:2:3:4:5:6:7", -1); \
448 bad("1:2:3:4:5:6:7:8:9", -1); \
449 bad("::1:", -1); \
450 bad("fe800::", -1); \
451 bad("stuv", -1); \
452 /* RFC 5952 recommendations */ \
453 good("2001:0db8::0001", "2001:db8::1"); \
454 good("2001:db8:0:0:0:0:2:1", "2001:db8::2:1"); \
455 good("2001:db8:0:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"); \
456 good("2001:0:0:1:0:0:0:1", "2001:0:0:1::1"); \
457 good("2001:db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"); \
458 good("0:1:A:B:C:D:E:F", "0:1:a:b:c:d:e:f"); \
459
START_TEST(test_ipv4_address)460 START_TEST(test_ipv4_address)
461 {
462 DESCRIBE_TEST;
463
464 #define GOOD(str, normalized) \
465 { \
466 struct cork_ipv4 addr; \
467 fail_if_error(cork_ipv4_init(&addr, str)); \
468 char actual[CORK_IPV4_STRING_LENGTH]; \
469 cork_ipv4_to_raw_string(&addr, actual); \
470 fail_unless(strcmp(actual, normalized) == 0, \
471 "Unexpected string representation: " \
472 "got \"%s\", expected \"%s\"", \
473 actual, normalized); \
474 \
475 struct cork_ipv4 addr2; \
476 cork_ipv4_init(&addr2, normalized); \
477 fail_unless(cork_ipv4_equal(&addr, &addr2), \
478 "IPv4 instances should be equal"); \
479 }
480
481 #define BAD(str, unused) \
482 { \
483 struct cork_ipv4 addr; \
484 fail_unless_error \
485 (cork_ipv4_init(&addr, str), \
486 "Shouldn't be able to initialize IPv4 address from \"%s\"", \
487 str); \
488 }
489
490 IPV4_TESTS(GOOD, BAD);
491 IPV6_TESTS(BAD, BAD);
492
493 #undef GOOD
494 #undef BAD
495
496 struct cork_ipv4 addr4;
497 unsigned int ipv4_cidr_good = 30;
498 unsigned int ipv4_cidr_bad_value = 24;
499 unsigned int ipv4_cidr_bad_range = 33;
500
501 fprintf(stderr, "Testing network prefixes\n");
502 cork_ipv4_init(&addr4, "1.2.3.4");
503 fail_unless(cork_ipv4_is_valid_network(&addr4, ipv4_cidr_good),
504 "Bad CIDR block for 1.2.3.4 and %u",
505 ipv4_cidr_good);
506 fail_if(cork_ipv4_is_valid_network(&addr4, ipv4_cidr_bad_value),
507 "IPv4 CIDR check should fail for %u",
508 ipv4_cidr_bad_value);
509 fail_if(cork_ipv4_is_valid_network(&addr4, ipv4_cidr_bad_range),
510 "IPv4 CIDR check should fail for %u",
511 ipv4_cidr_bad_range);
512 }
513 END_TEST
514
515
START_TEST(test_ipv6_address)516 START_TEST(test_ipv6_address)
517 {
518 DESCRIBE_TEST;
519
520 #define GOOD(str, normalized) \
521 { \
522 struct cork_ipv6 addr; \
523 fail_if_error(cork_ipv6_init(&addr, str)); \
524 char actual[CORK_IPV6_STRING_LENGTH]; \
525 cork_ipv6_to_raw_string(&addr, actual); \
526 fail_unless(strcmp(actual, normalized) == 0, \
527 "Unexpected string representation: " \
528 "got \"%s\", expected \"%s\"", \
529 actual, normalized); \
530 \
531 struct cork_ipv6 addr2; \
532 cork_ipv6_init(&addr2, normalized); \
533 fail_unless(cork_ipv6_equal(&addr, &addr2), \
534 "IPv6 instances should be equal"); \
535 }
536
537 #define BAD(str, unused) \
538 { \
539 struct cork_ipv6 addr; \
540 fail_unless_error \
541 (cork_ipv6_init(&addr, str), \
542 "Shouldn't be able to initialize IPv6 address from \"%s\"", \
543 str); \
544 }
545
546 IPV6_TESTS(GOOD, BAD);
547 IPV4_TESTS(BAD, BAD);
548
549 #undef GOOD
550 #undef BAD
551
552 struct cork_ipv6 addr6;
553 unsigned int ipv6_cidr_good = 127;
554 unsigned int ipv6_cidr_bad_value = 64;
555 unsigned int ipv6_cidr_bad_range = 129;
556
557 fprintf(stderr, "Testing network prefixes\n");
558 cork_ipv6_init(&addr6, "fe80::200:f8ff:fe21:6000");
559 fail_unless(cork_ipv6_is_valid_network(&addr6, ipv6_cidr_good),
560 "Bad CIDR block %u",
561 ipv6_cidr_good);
562 fail_if(cork_ipv6_is_valid_network(&addr6, ipv6_cidr_bad_value),
563 "IPv6 CIDR check should fail for %u",
564 ipv6_cidr_bad_value);
565 fail_if(cork_ipv6_is_valid_network(&addr6, ipv6_cidr_bad_range),
566 "IPv6 CIDR check should fail for %u",
567 ipv6_cidr_bad_range);
568 }
569 END_TEST
570
571
START_TEST(test_ip_address)572 START_TEST(test_ip_address)
573 {
574 DESCRIBE_TEST;
575 struct cork_ip addr;
576
577 #define GOOD(str, normalized) \
578 { \
579 struct cork_ip addr; \
580 fail_if_error(cork_ip_init(&addr, str)); \
581 char actual[CORK_IP_STRING_LENGTH]; \
582 cork_ip_to_raw_string(&addr, actual); \
583 fail_unless(strcmp(actual, normalized) == 0, \
584 "Unexpected string representation: " \
585 "got \"%s\", expected \"%s\"", \
586 actual, normalized); \
587 \
588 struct cork_ip addr2; \
589 cork_ip_init(&addr2, normalized); \
590 fail_unless(cork_ip_equal(&addr, &addr2), \
591 "IP instances should be equal"); \
592 }
593
594 #define BAD(str, unused) \
595 { \
596 struct cork_ip addr; \
597 fail_unless_error \
598 (cork_ip_init(&addr, str), \
599 "Shouldn't be able to initialize IP address from \"%s\"", \
600 str); \
601 }
602
603 IPV4_TESTS(GOOD, BAD);
604 IPV6_TESTS(GOOD, BAD);
605
606 #undef GOOD
607 #undef BAD
608
609 struct cork_ipv4 addr4;
610 struct cork_ipv6 addr6;
611
612 fprintf(stderr, "Testing IP address versions\n");
613 cork_ip_init(&addr, "192.168.1.1");
614 cork_ipv4_init(&addr4, "192.168.1.1");
615 fail_unless(addr.version == 4,
616 "Unexpected IP address version (expected 4, got %u)",
617 addr.version);
618 fail_unless(cork_ipv4_equal(&addr.ip.v4, &addr4),
619 "IP addresses should be equal");
620
621 cork_ip_init(&addr, "fe80::1");
622 cork_ipv6_init(&addr6, "fe80::1");
623 fail_unless(addr.version == 6,
624 "Unexpected IP address version (expected 6, got %u)",
625 addr.version);
626 fail_unless(cork_ipv6_equal(&addr.ip.v6, &addr6),
627 "IP addresses should be equal");
628 }
629 END_TEST
630
631
632 /*-----------------------------------------------------------------------
633 * Timestamps
634 */
635
636 static void
test_timestamp_bad_format(cork_timestamp ts,const char * format)637 test_timestamp_bad_format(cork_timestamp ts, const char *format)
638 {
639 struct cork_buffer buf = CORK_BUFFER_INIT();
640 fail_unless_error(cork_timestamp_format_utc(ts, format, &buf));
641 cork_buffer_done(&buf);
642 }
643
644 static void
test_timestamp_utc_format(cork_timestamp ts,const char * format,const char * expected)645 test_timestamp_utc_format(cork_timestamp ts, const char *format,
646 const char *expected)
647 {
648 struct cork_buffer buf = CORK_BUFFER_INIT();
649 fail_if_error(cork_timestamp_format_utc(ts, format, &buf));
650 fail_unless(strcmp(buf.buf, expected) == 0,
651 "Unexpected formatted UTC time "
652 "(got \"%s\", expected \"%s\")",
653 (char *) buf.buf, expected);
654 cork_buffer_done(&buf);
655 }
656
657 static void
test_timestamp_local_format(cork_timestamp ts,const char * format,const char * expected)658 test_timestamp_local_format(cork_timestamp ts, const char *format,
659 const char *expected)
660 {
661 struct cork_buffer buf = CORK_BUFFER_INIT();
662 fail_if_error(cork_timestamp_format_local(ts, format, &buf));
663 fail_unless(strcmp(buf.buf, expected) == 0,
664 "Unexpected formatted local time "
665 "(got \"%s\", expected \"%s\")",
666 (char *) buf.buf, expected);
667 cork_buffer_done(&buf);
668 }
669
START_TEST(test_timestamp)670 START_TEST(test_timestamp)
671 {
672 /* All of the local times here are in America/Los_Angeles. Down at the
673 * bottom of the file we override the TZ environment variable to ensure that
674 * we use a consistent local time zone in the test cases, regardless of the
675 * actual time zone of the current machine. */
676
677 static const uint32_t TEST_TIME_1 = 700000000;
678 static const char *FORMATTED_UTC_TIME_1 = " 1992-03-07 20:26:40 ";
679 static const char *FORMATTED_LOCAL_TIME_1 = " 1992-03-07 12:26:40 ";
680
681 static const uint32_t TEST_TIME_2 = 1200000000;
682 static const char *FORMATTED_UTC_TIME_2 = " 2008-01-10 21:20:00 ";
683 static const char *FORMATTED_LOCAL_TIME_2 = " 2008-01-10 13:20:00 ";
684
685 static const uint32_t TEST_TIME_3 = 1305180745;
686 static const char *FORMATTED_UTC_TIME_3 = " 2011-05-12 06:12:25 ";
687 static const char *FORMATTED_LOCAL_TIME_3 = " 2011-05-11 23:12:25 ";
688
689 cork_timestamp ts;
690
691 DESCRIBE_TEST;
692
693 #define test(unit, expected) \
694 fail_unless(cork_timestamp_##unit(ts) == expected, \
695 "Unexpected " #unit " portion of timestamp " \
696 "(got %lu, expected %lu)", \
697 (unsigned long) cork_timestamp_##unit(ts), \
698 (unsigned long) expected);
699
700 #define test_format(utc, local) \
701 test_timestamp_utc_format(ts, " %Y-%m-%d %H:%M:%S ", utc); \
702 test_timestamp_local_format(ts, " %Y-%m-%d %H:%M:%S ", local);
703
704 cork_timestamp_init_sec(&ts, TEST_TIME_1);
705 test(sec, TEST_TIME_1);
706 test(gsec, 0);
707 test(msec, 0);
708 test(usec, 0);
709 test(nsec, 0);
710 test_format(FORMATTED_UTC_TIME_1, FORMATTED_LOCAL_TIME_1);
711
712 cork_timestamp_init_sec(&ts, TEST_TIME_2);
713 test(sec, TEST_TIME_2);
714 test(gsec, 0);
715 test(msec, 0);
716 test(usec, 0);
717 test(nsec, 0);
718 test_format(FORMATTED_UTC_TIME_2, FORMATTED_LOCAL_TIME_2);
719
720 cork_timestamp_init_sec(&ts, TEST_TIME_3);
721 test(sec, TEST_TIME_3);
722 test(gsec, 0);
723 test(msec, 0);
724 test(usec, 0);
725 test(nsec, 0);
726 test_format(FORMATTED_UTC_TIME_3, FORMATTED_LOCAL_TIME_3);
727
728 cork_timestamp_init_gsec(&ts, TEST_TIME_1, 1 << 30);
729 test(sec, TEST_TIME_1);
730 test(gsec, 1 << 30);
731 test(msec, 250);
732 test(usec, 250000);
733 test(nsec, 250000000);
734
735 cork_timestamp_init_msec(&ts, TEST_TIME_1, 500);
736 test(sec, TEST_TIME_1);
737 test(gsec, 1 << 31);
738 test(msec, 500);
739 test(usec, 500000);
740 test(nsec, 500000000);
741
742 cork_timestamp_init_usec(&ts, TEST_TIME_1, 500000);
743 test(sec, TEST_TIME_1);
744 test(gsec, 1 << 31);
745 test(msec, 500);
746 test(usec, 500000);
747 test(nsec, 500000000);
748
749 cork_timestamp_init_nsec(&ts, TEST_TIME_1, 500000000);
750 test(sec, TEST_TIME_1);
751 test(gsec, 1 << 31);
752 test(msec, 500);
753 test(usec, 500000);
754 test(nsec, 500000000);
755 }
756 END_TEST
757
START_TEST(test_timestamp_format)758 START_TEST(test_timestamp_format)
759 {
760 cork_timestamp ts;
761 DESCRIBE_TEST;
762
763 cork_timestamp_init_nsec(&ts, 0, 123456789);
764 test_timestamp_bad_format(ts, "%f");
765 test_timestamp_bad_format(ts, "%0f");
766 test_timestamp_bad_format(ts, "%10f");
767 test_timestamp_utc_format(ts, "%1f", "1");
768 test_timestamp_utc_format(ts, "%2f", "12");
769 test_timestamp_utc_format(ts, "%3f", "123");
770 test_timestamp_utc_format(ts, "%4f", "1235");
771 test_timestamp_utc_format(ts, "%5f", "12346");
772 test_timestamp_utc_format(ts, "%6f", "123457");
773 test_timestamp_utc_format(ts, "%7f", "1234568");
774 test_timestamp_utc_format(ts, "%8f", "12345679");
775 test_timestamp_utc_format(ts, "%9f", "123456789");
776 test_timestamp_utc_format(ts, "%009f", "123456789");
777
778 cork_timestamp_init_nsec(&ts, 1200000000, 123456789);
779 }
780 END_TEST
781
782
783 /*-----------------------------------------------------------------------
784 * 128-bit integers
785 */
786
787 static void
test_one_u128_decimal(cork_u128 value,const char * expected)788 test_one_u128_decimal(cork_u128 value, const char *expected)
789 {
790 char buf[CORK_U128_DECIMAL_LENGTH];
791 const char *actual = cork_u128_to_decimal(buf, value);
792 fail_unless_streq("Integers", expected, actual);
793 }
794
795 static void
test_one_u128_hex(cork_u128 value,const char * expected)796 test_one_u128_hex(cork_u128 value, const char *expected)
797 {
798 char buf[CORK_U128_HEX_LENGTH];
799 const char *actual = cork_u128_to_hex(buf, value);
800 fail_unless_streq("Integers", expected, actual);
801 }
802
803 static void
test_one_u128_padded_hex(cork_u128 value,const char * expected)804 test_one_u128_padded_hex(cork_u128 value, const char *expected)
805 {
806 char buf[CORK_U128_HEX_LENGTH];
807 const char *actual = cork_u128_to_padded_hex(buf, value);
808 fail_unless_streq("Integers", expected, actual);
809 }
810
811 static void
test_one_u128_print_from_32(uint32_t i0,uint32_t i1,uint32_t i2,uint32_t i3,const char * expected_decimal,const char * expected_hex,const char * expected_padded_hex)812 test_one_u128_print_from_32(uint32_t i0, uint32_t i1, uint32_t i2, uint32_t i3,
813 const char *expected_decimal,
814 const char *expected_hex,
815 const char *expected_padded_hex)
816 {
817 cork_u128 value = cork_u128_from_32(i0, i1, i2, i3);
818 test_one_u128_decimal(value, expected_decimal);
819 test_one_u128_hex(value, expected_hex);
820 test_one_u128_padded_hex(value, expected_padded_hex);
821 }
822
823 static void
test_one_u128_print_from_64(uint64_t i0,uint64_t i1,const char * expected_decimal,const char * expected_hex,const char * expected_padded_hex)824 test_one_u128_print_from_64(uint64_t i0, uint64_t i1,
825 const char *expected_decimal,
826 const char *expected_hex,
827 const char *expected_padded_hex)
828 {
829 cork_u128 value = cork_u128_from_64(i0, i1);
830 test_one_u128_decimal(value, expected_decimal);
831 test_one_u128_hex(value, expected_hex);
832 test_one_u128_padded_hex(value, expected_padded_hex);
833 }
834
START_TEST(test_u128_print)835 START_TEST(test_u128_print)
836 {
837 DESCRIBE_TEST;
838 test_one_u128_print_from_32(
839 0, 0, 0, 0,
840 "0",
841 "0",
842 "00000000000000000000000000000000"
843 );
844 test_one_u128_print_from_32(
845 0, 0, 0, 2,
846 "2",
847 "2",
848 "00000000000000000000000000000002"
849 );
850 test_one_u128_print_from_32(
851 0, 0, 0, 20,
852 "20",
853 "14",
854 "00000000000000000000000000000014"
855 );
856 test_one_u128_print_from_32(
857 0, 0, 0, 0xffffffff,
858 "4294967295",
859 "ffffffff",
860 "000000000000000000000000ffffffff"
861 );
862 test_one_u128_print_from_32(
863 0, 0, 1, 0,
864 "4294967296",
865 "100000000",
866 "00000000000000000000000100000000"
867 );
868 test_one_u128_print_from_32(
869 0, 0, 0xffffffff, 0xffffffff,
870 "18446744073709551615",
871 "ffffffffffffffff",
872 "0000000000000000ffffffffffffffff"
873 );
874 test_one_u128_print_from_32(
875 0, 1, 0, 0,
876 "18446744073709551616",
877 "10000000000000000",
878 "00000000000000010000000000000000"
879 );
880 test_one_u128_print_from_64(
881 0, 0,
882 "0",
883 "0",
884 "00000000000000000000000000000000"
885 );
886 test_one_u128_print_from_64(
887 0, 2,
888 "2",
889 "2",
890 "00000000000000000000000000000002"
891 );
892 test_one_u128_print_from_64(
893 0, 20,
894 "20",
895 "14",
896 "00000000000000000000000000000014"
897 );
898 test_one_u128_print_from_64(
899 0, UINT64_C(0xffffffffffffffff),
900 "18446744073709551615",
901 "ffffffffffffffff",
902 "0000000000000000ffffffffffffffff"
903 );
904 test_one_u128_print_from_64(
905 1, 0,
906 "18446744073709551616",
907 "10000000000000000",
908 "00000000000000010000000000000000"
909 );
910 }
911 END_TEST
912
913
914 static void
test_one_u128_add(uint64_t i0,uint64_t i1,uint64_t j0,uint64_t j1,const char * expected)915 test_one_u128_add(uint64_t i0, uint64_t i1, uint64_t j0, uint64_t j1,
916 const char *expected)
917 {
918 cork_u128 value1 = cork_u128_from_64(i0, i1);
919 cork_u128 value2 = cork_u128_from_64(j0, j1);
920 cork_u128 sum = cork_u128_add(value1, value2);
921 test_one_u128_decimal(sum, expected);
922 }
923
START_TEST(test_u128_add)924 START_TEST(test_u128_add)
925 {
926 DESCRIBE_TEST;
927 test_one_u128_add(0, 0, 0, 0, "0");
928 test_one_u128_add(0, 1, 0, 1, "2");
929 test_one_u128_add(0, 1, 0, 0xffffffff, "4294967296");
930 test_one_u128_add(0, 1, 0xffffffffffffffffLL, 0xffffffffffffffffLL, "0");
931 }
932 END_TEST
933
934
935 static void
test_one_u128_sub(uint64_t i0,uint64_t i1,uint64_t j0,uint64_t j1,const char * expected)936 test_one_u128_sub(uint64_t i0, uint64_t i1, uint64_t j0, uint64_t j1,
937 const char *expected)
938 {
939 cork_u128 value1 = cork_u128_from_64(i0, i1);
940 cork_u128 value2 = cork_u128_from_64(j0, j1);
941 cork_u128 diff = cork_u128_sub(value1, value2);
942 test_one_u128_decimal(diff, expected);
943 }
944
START_TEST(test_u128_sub)945 START_TEST(test_u128_sub)
946 {
947 DESCRIBE_TEST;
948 test_one_u128_sub(0, 0, 0, 0, "0");
949 test_one_u128_sub(0, 1, 0, 1, "0");
950 test_one_u128_sub(0, 2, 0, 1, "1");
951 test_one_u128_sub(0, UINT64_C(0x100000000), 0, 1, "4294967295");
952 test_one_u128_sub(1, 0, 0, 1, "18446744073709551615");
953 test_one_u128_sub(0, 1, 0, 2, "340282366920938463463374607431768211455");
954 }
955 END_TEST
956
957
958 #define test_u128_cmp(op, op_str, v1, v2, expected) \
959 do { \
960 bool actual = cork_u128_##op((v1), (v2)); \
961 fail_unless(actual == (expected), \
962 "%" PRIu64 ":%" PRIu64 \
963 " should %sbe " op_str " " \
964 "%" PRIu64 ":%" PRIu64, \
965 cork_u128_be64((v1), 0), cork_u128_be64((v1), 1), \
966 (expected)? "": "not ", \
967 cork_u128_be64((v2), 0), cork_u128_be64((v2), 1)); \
968 } while (0)
969
970 static void
test_one_u128_eq(uint64_t i0,uint64_t i1,uint64_t j0,uint64_t j1,bool expected)971 test_one_u128_eq(uint64_t i0, uint64_t i1, uint64_t j0, uint64_t j1,
972 bool expected)
973 {
974 cork_u128 value1 = cork_u128_from_64(i0, i1);
975 cork_u128 value2 = cork_u128_from_64(j0, j1);
976 test_u128_cmp(eq, "==", value1, value2, expected);
977 test_u128_cmp(ne, "!=", value1, value2, !expected);
978 }
979
START_TEST(test_u128_eq)980 START_TEST(test_u128_eq)
981 {
982 DESCRIBE_TEST;
983 test_one_u128_eq(0, 0, 0, 0, true);
984 test_one_u128_eq(0, 0, 0, 1, false);
985 test_one_u128_eq(0, 2, 0, 1, false);
986 test_one_u128_eq(0, 1, 0, UINT64_C(0x100000000), false);
987 test_one_u128_eq(0, UINT64_C(0x100000000), 0, UINT64_C(0x100000000), true);
988 }
989 END_TEST
990
991 static void
test_one_u128_lt(uint64_t i0,uint64_t i1,uint64_t j0,uint64_t j1,bool expected)992 test_one_u128_lt(uint64_t i0, uint64_t i1, uint64_t j0, uint64_t j1,
993 bool expected)
994 {
995 cork_u128 value1 = cork_u128_from_64(i0, i1);
996 cork_u128 value2 = cork_u128_from_64(j0, j1);
997 test_u128_cmp(lt, "<", value1, value2, expected);
998 test_u128_cmp(ge, ">=", value1, value2, !expected);
999 }
1000
START_TEST(test_u128_lt)1001 START_TEST(test_u128_lt)
1002 {
1003 DESCRIBE_TEST;
1004 test_one_u128_lt(0, 0, 0, 0, false);
1005 test_one_u128_lt(0, 0, 0, 1, true);
1006 test_one_u128_lt(0, 2, 0, 1, false);
1007 test_one_u128_lt(0, 1, 0, UINT64_C(0x100000000), true);
1008 }
1009 END_TEST
1010
1011 static void
test_one_u128_gt(uint64_t i0,uint64_t i1,uint64_t j0,uint64_t j1,bool expected)1012 test_one_u128_gt(uint64_t i0, uint64_t i1, uint64_t j0, uint64_t j1,
1013 bool expected)
1014 {
1015 cork_u128 value1 = cork_u128_from_64(i0, i1);
1016 cork_u128 value2 = cork_u128_from_64(j0, j1);
1017 test_u128_cmp(gt, ">", value1, value2, expected);
1018 test_u128_cmp(le, "<=", value1, value2, !expected);
1019 }
1020
START_TEST(test_u128_gt)1021 START_TEST(test_u128_gt)
1022 {
1023 DESCRIBE_TEST;
1024 test_one_u128_gt(0, 0, 0, 0, false);
1025 test_one_u128_gt(0, 1, 0, 0, true);
1026 test_one_u128_gt(0, 1, 0, 2, false);
1027 test_one_u128_gt(0, UINT64_C(0x100000000), 0, 1, true);
1028 }
1029 END_TEST
1030
1031
1032 /*-----------------------------------------------------------------------
1033 * Statement expressions
1034 */
1035
START_TEST(test_statement_expr)1036 START_TEST(test_statement_expr)
1037 {
1038 #if CORK_CONFIG_HAVE_GCC_STATEMENT_EXPRS
1039 int value = ({ int __x = 0; __x += 2; __x;});
1040 fail_unless_equal("Statement expression result", "%d", 2, value);
1041 #endif
1042 }
1043 END_TEST
1044
1045
1046 /*-----------------------------------------------------------------------
1047 * Unique identifiers
1048 */
1049
START_TEST(test_uid)1050 START_TEST(test_uid)
1051 {
1052 DESCRIBE_TEST;
1053 cork_uid_define(test_id_01);
1054 cork_uid_define(test_id_02);
1055 cork_uid id1;
1056 cork_uid id2;
1057
1058 fail_unless_streq("UID name", "test_id_01", cork_uid_name(test_id_01));
1059 fail_unless_streq("UID name", "test_id_02", cork_uid_name(test_id_02));
1060
1061 id1 = test_id_01;
1062 id2 = test_id_02;
1063 fail_if(cork_uid_equal(id1, id2), "Unique IDs aren't unique");
1064
1065 id1 = test_id_01;
1066 id2 = test_id_01;
1067 fail_unless(cork_uid_equal(id1, id2), "Unique ID isn't equal to itself");
1068
1069 id1 = test_id_01;
1070 id2 = CORK_UID_NONE;
1071 fail_if(cork_uid_equal(id1, id2), "NULL unique ID isn't unique");
1072 }
1073 END_TEST
1074
1075
1076 /*-----------------------------------------------------------------------
1077 * Testing harness
1078 */
1079
1080 Suite *
test_suite()1081 test_suite()
1082 {
1083 Suite *s = suite_create("core");
1084
1085 TCase *tc_types = tcase_create("types");
1086 tcase_add_test(tc_types, test_bool);
1087 tcase_add_test(tc_types, test_int_types);
1088 tcase_add_test(tc_types, test_int_sizeof);
1089 suite_add_tcase(s, tc_types);
1090
1091 TCase *tc_string = tcase_create("string");
1092 tcase_add_test(tc_string, test_string);
1093 suite_add_tcase(s, tc_string);
1094
1095 TCase *tc_endianness = tcase_create("endianness");
1096 tcase_add_test(tc_endianness, test_endianness);
1097 suite_add_tcase(s, tc_endianness);
1098
1099 TCase *tc_errors = tcase_create("errors");
1100 tcase_add_test(tc_errors, test_error_prefix);
1101 tcase_add_test(tc_errors, test_system_error);
1102 suite_add_tcase(s, tc_errors);
1103
1104 TCase *tc_hash = tcase_create("hash");
1105 tcase_add_test(tc_hash, test_hash);
1106 suite_add_tcase(s, tc_hash);
1107
1108 TCase *tc_addresses = tcase_create("net-addresses");
1109 tcase_add_test(tc_addresses, test_ipv4_address);
1110 tcase_add_test(tc_addresses, test_ipv6_address);
1111 tcase_add_test(tc_addresses, test_ip_address);
1112 suite_add_tcase(s, tc_addresses);
1113
1114 TCase *tc_timestamp = tcase_create("timestamp");
1115 tcase_add_test(tc_timestamp, test_timestamp);
1116 tcase_add_test(tc_timestamp, test_timestamp_format);
1117 suite_add_tcase(s, tc_timestamp);
1118
1119 TCase *tc_u128 = tcase_create("u128");
1120 tcase_add_test(tc_u128, test_u128_print);
1121 tcase_add_test(tc_u128, test_u128_add);
1122 tcase_add_test(tc_u128, test_u128_sub);
1123 tcase_add_test(tc_u128, test_u128_eq);
1124 tcase_add_test(tc_u128, test_u128_lt);
1125 tcase_add_test(tc_u128, test_u128_gt);
1126 suite_add_tcase(s, tc_u128);
1127
1128 TCase *tc_statement_expr = tcase_create("statement_expr");
1129 tcase_add_test(tc_statement_expr, test_statement_expr);
1130 suite_add_tcase(s, tc_statement_expr);
1131
1132 TCase *tc_uid = tcase_create("uid");
1133 tcase_add_test(tc_uid, test_uid);
1134 suite_add_tcase(s, tc_uid);
1135
1136 return s;
1137 }
1138
1139
1140 int
main(int argc,const char ** argv)1141 main(int argc, const char **argv)
1142 {
1143 int number_failed;
1144 Suite *suite = test_suite();
1145 SRunner *runner = srunner_create(suite);
1146
1147 setup_allocator();
1148
1149 /* Before anything starts, override the TZ environment variable so that we
1150 * get consistent test results. */
1151 cork_env_add(NULL, "TZ", "America/Los_Angeles");
1152
1153 srunner_run_all(runner, CK_NORMAL);
1154 number_failed = srunner_ntests_failed(runner);
1155 srunner_free(runner);
1156
1157 return (number_failed == 0)? EXIT_SUCCESS: EXIT_FAILURE;
1158 }
1159