1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 #if HAVE_CMOCKA
13
14 #include <inttypes.h>
15 #include <sched.h> /* IWYU pragma: keep */
16 #include <setjmp.h>
17 #include <stdarg.h>
18 #include <stddef.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include <unistd.h>
23
24 #define UNIT_TESTING
25 #include <cmocka.h>
26
27 #include <isc/serial.h>
28 #include <isc/stdtime.h>
29 #include <isc/util.h>
30
31 #include <dns/update.h>
32
33 #include "dnstest.h"
34
35 /*
36 * Fix the linking order problem for overridden isc_stdtime_get() by making
37 * everything local. This also allows static functions from update.c to be
38 * tested.
39 */
40 #include "../update.c"
41
42 static int
_setup(void ** state)43 _setup(void **state) {
44 isc_result_t result;
45
46 UNUSED(state);
47
48 result = dns_test_begin(NULL, false);
49 assert_int_equal(result, ISC_R_SUCCESS);
50
51 setenv("TZ", "", 1);
52
53 return (0);
54 }
55
56 static int
_teardown(void ** state)57 _teardown(void **state) {
58 UNUSED(state);
59
60 dns_test_end();
61
62 return (0);
63 }
64
65 static uint32_t mystdtime;
66
67 static void
set_mystdtime(int year,int month,int day)68 set_mystdtime(int year, int month, int day) {
69 struct tm tm;
70
71 memset(&tm, 0, sizeof(tm));
72 tm.tm_year = year - 1900;
73 tm.tm_mon = month - 1;
74 tm.tm_mday = day;
75 mystdtime = timegm(&tm);
76 }
77
78 void
isc_stdtime_get(isc_stdtime_t * now)79 isc_stdtime_get(isc_stdtime_t *now) {
80 *now = mystdtime;
81 }
82
83 /* simple increment by 1 */
84 static void
increment_test(void ** state)85 increment_test(void **state) {
86 uint32_t old = 50;
87 uint32_t serial;
88
89 UNUSED(state);
90
91 serial = dns_update_soaserial(old, dns_updatemethod_increment, NULL);
92 assert_true(isc_serial_lt(old, serial));
93 assert_int_not_equal(serial, 0);
94 assert_int_equal(serial, 51);
95 }
96
97 /* increment past zero, 0xfffffffff -> 1 */
98 static void
increment_past_zero_test(void ** state)99 increment_past_zero_test(void **state) {
100 uint32_t old = 0xffffffffu;
101 uint32_t serial;
102
103 UNUSED(state);
104
105 serial = dns_update_soaserial(old, dns_updatemethod_increment, NULL);
106 assert_true(isc_serial_lt(old, serial));
107 assert_int_not_equal(serial, 0);
108 assert_int_equal(serial, 1u);
109 }
110
111 /* past to unixtime */
112 static void
past_to_unix_test(void ** state)113 past_to_unix_test(void **state) {
114 uint32_t old;
115 uint32_t serial;
116
117 UNUSED(state);
118
119 set_mystdtime(2011, 6, 22);
120 old = mystdtime - 1;
121
122 serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
123 assert_true(isc_serial_lt(old, serial));
124 assert_int_not_equal(serial, 0);
125 assert_int_equal(serial, mystdtime);
126 }
127
128 /* now to unixtime */
129 static void
now_to_unix_test(void ** state)130 now_to_unix_test(void **state) {
131 uint32_t old;
132 uint32_t serial;
133
134 UNUSED(state);
135
136 set_mystdtime(2011, 6, 22);
137 old = mystdtime;
138
139 serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
140 assert_true(isc_serial_lt(old, serial));
141 assert_int_not_equal(serial, 0);
142 assert_int_equal(serial, old + 1);
143 }
144
145 /* future to unixtime */
146 static void
future_to_unix_test(void ** state)147 future_to_unix_test(void **state) {
148 uint32_t old;
149 uint32_t serial;
150
151 UNUSED(state);
152
153 set_mystdtime(2011, 6, 22);
154 old = mystdtime + 1;
155
156 serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
157 assert_true(isc_serial_lt(old, serial));
158 assert_int_not_equal(serial, 0);
159 assert_int_equal(serial, old + 1);
160 }
161
162 /* undefined plus 1 to unixtime */
163 static void
undefined_plus1_to_unix_test(void ** state)164 undefined_plus1_to_unix_test(void **state) {
165 uint32_t old;
166 uint32_t serial;
167
168 UNUSED(state);
169
170 set_mystdtime(2011, 6, 22);
171 old = mystdtime ^ 0x80000000u;
172 old += 1;
173
174 serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
175 assert_true(isc_serial_lt(old, serial));
176 assert_int_not_equal(serial, 0);
177 assert_int_equal(serial, mystdtime);
178 }
179
180 /* undefined minus 1 to unixtime */
181 static void
undefined_minus1_to_unix_test(void ** state)182 undefined_minus1_to_unix_test(void **state) {
183 uint32_t old;
184 uint32_t serial;
185
186 UNUSED(state);
187
188 set_mystdtime(2011, 6, 22);
189 old = mystdtime ^ 0x80000000u;
190 old -= 1;
191
192 serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
193 assert_true(isc_serial_lt(old, serial));
194 assert_int_not_equal(serial, 0);
195 assert_int_equal(serial, old + 1);
196 }
197
198 /* undefined to unixtime */
199 static void
undefined_to_unix_test(void ** state)200 undefined_to_unix_test(void **state) {
201 uint32_t old;
202 uint32_t serial;
203
204 UNUSED(state);
205
206 set_mystdtime(2011, 6, 22);
207 old = mystdtime ^ 0x80000000u;
208
209 serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
210 assert_true(isc_serial_lt(old, serial));
211 assert_int_not_equal(serial, 0);
212 assert_int_equal(serial, old + 1);
213 }
214
215 /* handle unixtime being zero */
216 static void
unixtime_zero_test(void ** state)217 unixtime_zero_test(void **state) {
218 uint32_t old;
219 uint32_t serial;
220
221 UNUSED(state);
222
223 mystdtime = 0;
224 old = 0xfffffff0;
225
226 serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
227 assert_true(isc_serial_lt(old, serial));
228 assert_int_not_equal(serial, 0);
229 assert_int_equal(serial, old + 1);
230 }
231
232 /* past to date */
233 static void
past_to_date_test(void ** state)234 past_to_date_test(void **state) {
235 uint32_t old, serial;
236 dns_updatemethod_t used = dns_updatemethod_none;
237
238 UNUSED(state);
239
240 set_mystdtime(2014, 3, 31);
241 old = dns_update_soaserial(0, dns_updatemethod_date, NULL);
242 set_mystdtime(2014, 4, 1);
243
244 serial = dns_update_soaserial(old, dns_updatemethod_date, &used);
245 assert_true(isc_serial_lt(old, serial));
246 assert_int_not_equal(serial, 0);
247 assert_int_equal(serial, 2014040100);
248 assert_int_equal(dns_updatemethod_date, used);
249 }
250
251 /* now to date */
252 static void
now_to_date_test(void ** state)253 now_to_date_test(void **state) {
254 uint32_t old;
255 uint32_t serial;
256 dns_updatemethod_t used = dns_updatemethod_none;
257
258 UNUSED(state);
259
260 set_mystdtime(2014, 4, 1);
261 old = dns_update_soaserial(0, dns_updatemethod_date, NULL);
262
263 serial = dns_update_soaserial(old, dns_updatemethod_date, &used);
264 assert_true(isc_serial_lt(old, serial));
265 assert_int_not_equal(serial, 0);
266 assert_int_equal(serial, 2014040101);
267 assert_int_equal(dns_updatemethod_date, used);
268
269 old = 2014040198;
270 serial = dns_update_soaserial(old, dns_updatemethod_date, &used);
271 assert_true(isc_serial_lt(old, serial));
272 assert_int_not_equal(serial, 0);
273 assert_int_equal(serial, 2014040199);
274 assert_int_equal(dns_updatemethod_date, used);
275
276 /*
277 * Stealing from "tomorrow".
278 */
279 old = 2014040199;
280 serial = dns_update_soaserial(old, dns_updatemethod_date, &used);
281 assert_true(isc_serial_lt(old, serial));
282 assert_int_not_equal(serial, 0);
283 assert_int_equal(serial, 2014040200);
284 assert_int_equal(dns_updatemethod_increment, used);
285 }
286
287 /* future to date */
288 static void
future_to_date_test(void ** state)289 future_to_date_test(void **state) {
290 uint32_t old;
291 uint32_t serial;
292 dns_updatemethod_t used = dns_updatemethod_none;
293
294 UNUSED(state);
295
296 set_mystdtime(2014, 4, 1);
297 old = dns_update_soaserial(0, dns_updatemethod_date, NULL);
298 set_mystdtime(2014, 3, 31);
299
300 serial = dns_update_soaserial(old, dns_updatemethod_date, &used);
301 assert_true(isc_serial_lt(old, serial));
302 assert_int_not_equal(serial, 0);
303 assert_int_equal(serial, 2014040101);
304 assert_int_equal(dns_updatemethod_increment, used);
305
306 old = serial;
307 serial = dns_update_soaserial(old, dns_updatemethod_date, &used);
308 assert_true(isc_serial_lt(old, serial));
309 assert_int_not_equal(serial, 0);
310 assert_int_equal(serial, 2014040102);
311 assert_int_equal(dns_updatemethod_increment, used);
312 }
313
314 int
main(void)315 main(void) {
316 const struct CMUnitTest tests[] = {
317 cmocka_unit_test_setup_teardown(increment_test, _setup,
318 _teardown),
319 cmocka_unit_test_setup_teardown(increment_past_zero_test,
320 _setup, _teardown),
321 cmocka_unit_test_setup_teardown(past_to_unix_test, _setup,
322 _teardown),
323 cmocka_unit_test_setup_teardown(now_to_unix_test, _setup,
324 _teardown),
325 cmocka_unit_test_setup_teardown(future_to_unix_test, _setup,
326 _teardown),
327 cmocka_unit_test_setup_teardown(undefined_to_unix_test, _setup,
328 _teardown),
329 cmocka_unit_test_setup_teardown(undefined_plus1_to_unix_test,
330 _setup, _teardown),
331 cmocka_unit_test_setup_teardown(undefined_minus1_to_unix_test,
332 _setup, _teardown),
333 cmocka_unit_test_setup_teardown(unixtime_zero_test, _setup,
334 _teardown),
335 cmocka_unit_test_setup_teardown(past_to_date_test, _setup,
336 _teardown),
337 cmocka_unit_test_setup_teardown(now_to_date_test, _setup,
338 _teardown),
339 cmocka_unit_test_setup_teardown(future_to_date_test, _setup,
340 _teardown),
341 };
342
343 return (cmocka_run_group_tests(tests, NULL, NULL));
344 }
345
346 #else /* HAVE_CMOCKA */
347
348 #include <stdio.h>
349
350 int
main(void)351 main(void) {
352 printf("1..0 # Skipped: cmocka not available\n");
353 return (SKIPPED_TEST_EXIT_CODE);
354 }
355
356 #endif /* if HAVE_CMOCKA */
357