1 /*
2 * SysDB - t/unit/core/time_test.c
3 * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
28 #if HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include "core/time.h"
33 #include "testutils.h"
35 #include <check.h>
37 #define YEAR 3652425L * 24L * 3600L * 100000L
38 #define MONTH 30436875L * 24L * 3600L * 1000L
39 #define DAY 24L * 3600L * 1000000000L
40 #define HOUR 3600L * 1000000000L
41 #define MINUTE 60L * 1000000000L
42 #define SECOND 1000000000L
43 #define MS 1000000L
44 #define US 1000L
45 #define NS 1L
47 struct {
48 sdb_time_t t;
49 const char *tz;
50 const char *expected;
51 } strftime_data[] = {
52 { 0, "UTC", "1970-01-01 00:00:00 +0000" },
53 { 1428066243000000000L, "Europe/Berlin", "2015-04-03 15:04:03 +0200" },
54 { 1420113661000000000L, "Europe/Berlin", "2015-01-01 13:01:01 +0100" },
55 { 1428066243000000000L, "US/Pacific", "2015-04-03 06:04:03 -0700" },
56 { 1420113661000000000L, "US/Pacific", "2015-01-01 04:01:01 -0800" },
57 { 1146747723000000123L, "UTC", "2006-05-04 13:02:03.000000123 +0000" },
58 { 1146747723123456789L, "UTC", "2006-05-04 13:02:03.123456789 +0000" },
59 };
61 START_TEST(test_strftime)
62 {
63 char buf[1024], tz[64];
64 size_t check;
66 /* strftime does not provide the number of bytes that would have been
67 * written. Only check that it does not segfault. */
68 sdb_strftime(NULL, 0, strftime_data[_i].t);
70 snprintf(tz, sizeof(tz), "TZ=%s", strftime_data[_i].tz);
71 putenv(tz);
72 tzset();
74 check = sdb_strftime(buf, sizeof(buf), strftime_data[_i].t);
75 fail_unless(check > 0,
76 "%s; sdb_strftime(<buf>, <size>, %"PRIsdbTIME") = %zu; "
77 "expected: >0", tz, strftime_data[_i].t, check);
78 fail_unless(!strcmp(buf, strftime_data[_i].expected),
79 "%s; sdb_strftime(<buf>, <size>, %"PRIsdbTIME") did not "
80 "format time correctly; got: '%s'; expected: '%s'",
81 tz, strftime_data[_i].t, buf, strftime_data[_i].expected);
82 fail_unless(check == strlen(strftime_data[_i].expected),
83 "%s; sdb_strftime(<buf>, <size>, %"PRIsdbTIME") = %zu; "
84 "expected: %zu", tz, strftime_data[_i].t, check,
85 strlen(strftime_data[_i].expected));
87 putenv("TZ=UTC");
88 tzset();
89 }
90 END_TEST
92 struct {
93 sdb_time_t interval;
94 const char *expected;
95 } strfinterval_data[] = {
96 { 0, "0s" },
97 { 4711, ".000004711s" },
98 { 1000123400, "1.0001234s" },
99 { 47940228000000000L, "1Y6M7D" },
100 { YEAR, "1Y" },
101 { MONTH, "1M" },
102 { DAY, "1D" },
103 { HOUR, "1h" },
104 { MINUTE, "1m" },
105 { SECOND, "1s" },
106 { YEAR
107 + MONTH
108 + DAY
109 + HOUR
110 + MINUTE
111 + SECOND
112 + 1234, "1Y1M1D1h1m1.000001234s" },
113 };
115 START_TEST(test_strfinterval)
116 {
117 char buf[1024];
118 size_t check;
120 /* this should return the number of bytes which would have been written;
121 * in fact, it might return a bit more because it cannot detect trailing
122 * zeroes; even more importantly, it should not segfault ;-) */
123 check = sdb_strfinterval(NULL, 0, strfinterval_data[_i].interval);
124 fail_unless(check >= strlen(strfinterval_data[_i].expected),
125 "sdb_strfinterval(NULL, 0, %"PRIsdbTIME") = %zu; expected: %zu",
126 strfinterval_data[_i].interval, check,
127 strlen(strfinterval_data[_i].expected));
129 check = sdb_strfinterval(buf, sizeof(buf), strfinterval_data[_i].interval);
130 fail_unless(check > 0,
131 "sdb_strfinterval(<buf>, <size>, %"PRIsdbTIME") = %zu; "
132 "expected: >0", strfinterval_data[_i].interval, check);
133 fail_unless(!strcmp(buf, strfinterval_data[_i].expected),
134 "sdb_strfinterval(<buf>, <size>, %"PRIsdbTIME") did not "
135 "format interval correctly; got: '%s'; expected: '%s'",
136 strfinterval_data[_i].interval, buf, strfinterval_data[_i].expected);
137 fail_unless(check == strlen(strfinterval_data[_i].expected),
138 "sdb_strfinterval(<buf>, <size>, %"PRIsdbTIME") = %zu; "
139 "expected: %zu", strfinterval_data[_i].interval, check,
140 strlen(strfinterval_data[_i].expected));
141 }
142 END_TEST
144 struct {
145 const char *s;
146 sdb_time_t expected;
147 } strpunit_data[] = {
148 { "Y", YEAR },
149 { "M", MONTH },
150 { "D", DAY },
151 { "h", HOUR },
152 { "m", MINUTE },
153 { "s", SECOND },
154 { "ms", MS },
155 { "us", US },
156 { "ns", NS },
157 /* invalid units */
158 { "y", 0 },
159 { "d", 0 },
160 { "H", 0 },
161 { "S", 0 },
162 { "ps", 0 },
163 };
165 START_TEST(test_strpunit)
166 {
167 sdb_time_t check = sdb_strpunit(strpunit_data[_i].s);
169 fail_unless(check == strpunit_data[_i].expected,
170 "sdb_strpunit(%s) = %"PRIsdbTIME"; expected: %"PRIsdbTIME,
171 strpunit_data[_i].s, check, strpunit_data[_i].expected);
172 }
173 END_TEST
175 TEST_MAIN("core::time")
176 {
177 TCase *tc = tcase_create("core");
178 TC_ADD_LOOP_TEST(tc, strftime);
179 TC_ADD_LOOP_TEST(tc, strfinterval);
180 TC_ADD_LOOP_TEST(tc, strpunit);
181 ADD_TCASE(tc);
182 }
183 TEST_MAIN_END
185 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */