1 /*
2 * tlsdated-unittest.c - tlsdated unit tests
3 * Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "config.h"
9
10 #include "src/test_harness.h"
11 #include "src/tlsdate.h"
12 #include "src/util.h"
13
14 #include <event2/event.h>
15 #include <fcntl.h>
16 #include <limits.h>
17 #include <stdlib.h>
18 #include <sys/time.h>
19 #include <unistd.h>
20
FIXTURE(tempdir)21 FIXTURE (tempdir)
22 {
23 char path[PATH_MAX];
24 };
25
FIXTURE_SETUP(tempdir)26 FIXTURE_SETUP (tempdir)
27 {
28 char *p;
29 strncpy (self->path, "/tmp/tlsdated-unit-XXXXXX", sizeof (self->path));
30 p = mkdtemp (self->path);
31 ASSERT_NE (NULL, p);
32 }
33
FIXTURE_TEARDOWN(tempdir)34 FIXTURE_TEARDOWN(tempdir) {
35 char buf[256];
36 snprintf(buf, sizeof(buf), "%s/load", self->path);
37 unlink(buf);
38 snprintf(buf, sizeof(buf), "%s/save", self->path);
39 unlink(buf);
40 ASSERT_EQ(0, rmdir(self->path));
41 }
42
write_time(const char * path,time_t time)43 int write_time (const char *path, time_t time)
44 {
45 int fd = open (path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
46 if (fd == -1)
47 return 1;
48 if (save_timestamp_to_fd (fd, time))
49 return 1;
50 if (write (fd, &time, sizeof (time)) != sizeof (time))
51 {
52 close (fd);
53 return 1;
54 }
55 return close (fd);
56 }
57
read_time(const char * path,time_t * time)58 int read_time (const char *path, time_t* time)
59 {
60 int fd = open (path, O_RDONLY);
61 if (fd == -1)
62 return 1;
63 if (read (fd, time, sizeof (*time)) != sizeof (*time))
64 {
65 close (fd);
66 return 1;
67 }
68 return close (fd);
69 }
70
TEST(sane_time)71 TEST (sane_time)
72 {
73 ASSERT_EQ (0, is_sane_time (0));
74 ASSERT_EQ (0, is_sane_time (INT_MAX));
75 }
76
TEST(sane_host_time)77 TEST (sane_host_time)
78 {
79 ASSERT_EQ (1, is_sane_time (time (NULL)));
80 }
81
TEST_F(tempdir,load_time)82 TEST_F (tempdir, load_time)
83 {
84 char buf[PATH_MAX];
85 time_t tm = 3;
86 time_t now = time (NULL);
87 snprintf (buf, sizeof (buf), "%s/load", self->path);
88 ASSERT_EQ (0, write_time (buf, 0));
89 ASSERT_EQ (-1, load_disk_timestamp (buf, &tm));
90 ASSERT_EQ (3, tm);
91 ASSERT_EQ (0, write_time (buf, INT_MAX));
92 ASSERT_EQ (-1, load_disk_timestamp (buf, &tm));
93 ASSERT_EQ (3, tm);
94 ASSERT_EQ (0, write_time (buf, now));
95 ASSERT_EQ (0, truncate (buf, 2));
96 ASSERT_EQ (-1, load_disk_timestamp (buf, &tm));
97 ASSERT_EQ (3, tm);
98 ASSERT_EQ (0, unlink (buf));
99 ASSERT_EQ (-1, load_disk_timestamp (buf, &tm));
100 ASSERT_EQ (3, tm);
101 ASSERT_EQ (0, write_time (buf, now));
102 ASSERT_EQ (0, load_disk_timestamp (buf, &tm));
103 ASSERT_EQ (now, tm);
104 }
105
106
TEST_F(tempdir,save_time)107 TEST_F (tempdir, save_time)
108 {
109 char buf[PATH_MAX];
110 time_t now = time (NULL);
111 time_t tm;
112 snprintf (buf, sizeof (buf), "%s/save", self->path);
113 ASSERT_EQ (0, write_time (buf, now));
114 ASSERT_EQ (0, read_time (buf, &tm));
115 EXPECT_EQ (now, tm);
116 }
117
FIXTURE(tlsdate)118 FIXTURE (tlsdate)
119 {
120 struct state state;
121 struct timeval timeout;
122 };
123
124
FIXTURE_SETUP(tlsdate)125 FIXTURE_SETUP (tlsdate)
126 {
127 memset (self, 0, sizeof (*self));
128 /* TODO(wad) make this use the same function tlsdated uses. */
129 self->state.base = event_base_new();
130 set_conf_defaults (&self->state.opts);
131 ASSERT_NE (NULL, self->state.base);
132 event_base_priority_init (self->state.base, MAX_EVENT_PRIORITIES);
133 ASSERT_EQ (0, setup_sigchld_event (&self->state, 1));
134 self->state.events[E_TLSDATE] = event_new (self->state.base, -1, EV_TIMEOUT,
135 action_run_tlsdate, &self->state);
136 ASSERT_NE (NULL, self->state.events[E_TLSDATE]);
137 event_priority_set (self->state.events[E_TLSDATE], PRI_NET);
138 /* The timeout and fd will be filled in per-call. */
139 ASSERT_EQ (0, setup_tlsdate_status (&self->state));
140 self->timeout.tv_sec = 1;
141 }
142
FIXTURE_TEARDOWN(tlsdate)143 FIXTURE_TEARDOWN (tlsdate)
144 {
145 int i;
146 for (i = 0; i < E_MAX; ++i)
147 {
148 struct event *e = self->state.events[i];
149 if (e)
150 {
151 int fd = event_get_fd (e);
152 if (fd >= 0 && ! (event_get_events (e) & EV_SIGNAL))
153 close (fd);
154 event_free (e);
155 self->state.events[i] = NULL;
156 }
157 }
158 /* The other half was closed above. */
159 close (self->state.tlsdate_monitor_fd);
160 if (self->state.tlsdate_pid)
161 {
162 kill (self->state.tlsdate_pid, SIGKILL);
163 waitpid (self->state.tlsdate_pid, NULL, WNOHANG);
164 }
165 if (self->state.base)
166 event_base_free (self->state.base);
167 }
168
169 static int
runner(FIXTURE_DATA (tlsdate)* self,time_t * newtime)170 runner (FIXTURE_DATA (tlsdate) *self, time_t *newtime)
171 {
172 if (newtime)
173 *newtime = 0;
174 trigger_event (&self->state, E_TLSDATE, 0);
175 event_base_loopexit (self->state.base, &self->timeout);
176 if (event_base_dispatch (self->state.base))
177 return -1;
178 if (self->state.last_time)
179 {
180 if (newtime)
181 *newtime = self->state.last_time;
182 return 0;
183 }
184 return 1;
185 }
186
TEST_F(tlsdate,runner_multi)187 TEST_F (tlsdate, runner_multi)
188 {
189 struct source source =
190 {
191 .next = NULL,
192 .host = "host1",
193 .port = "port1",
194 .proxy = "proxy1"
195 };
196 char *args[] = { "/nonexistent", NULL, NULL };
197 extern char **environ;
198 self->state.opts.sources = &source;
199 self->state.opts.base_argv = args;
200 self->state.opts.subprocess_tries = 2;
201 self->state.opts.subprocess_wait_between_tries = 1;
202 self->state.opts.max_tries = 3;
203 self->state.envp = environ;
204 EXPECT_EQ (1, runner (self, NULL));
205 args[0] = "/bin/false";
206 self->state.tries = 0;
207 self->state.last_sync_type = SYNC_TYPE_NONE;
208 EXPECT_EQ (1, runner (self, NULL));
209 args[0] = "src/test/check-host-1";
210 self->state.tries = 0;
211 self->state.last_sync_type = SYNC_TYPE_NONE;
212 EXPECT_EQ (0, runner (self, NULL));
213 args[0] = "src/test/sleep-wrap";
214 args[1] = "3";
215 self->state.tries = 0;
216 self->state.last_sync_type = SYNC_TYPE_NONE;
217 EXPECT_EQ (0, runner (self, NULL));
218 }
219
TEST(jitter)220 TEST (jitter)
221 {
222 int i = 0;
223 int r;
224 const int kBase = 100;
225 const int kJitter = 25;
226 int nonequal = 0;
227 for (i = 0; i < 1000; i++)
228 {
229 r = add_jitter (kBase, kJitter);
230 EXPECT_GE (r, kBase - kJitter);
231 EXPECT_LE (r, kBase + kJitter);
232 if (r != kBase)
233 nonequal++;
234 }
235 EXPECT_NE (nonequal, 0);
236 }
237
TEST_F(tlsdate,rotate_hosts)238 TEST_F (tlsdate, rotate_hosts)
239 {
240 struct source s2 =
241 {
242 .next = NULL,
243 .host = "host2",
244 .port = "port2",
245 .proxy = "proxy2"
246 };
247 struct source s1 =
248 {
249 .next = &s2,
250 .host = "host1",
251 .port = "port1",
252 .proxy = "proxy1"
253 };
254 char *args[] = { "src/test/check-host-1", NULL };
255 extern char **environ;
256 self->state.envp = environ;
257 self->state.opts.sources = &s1;
258 self->state.opts.base_argv = args;
259 self->state.opts.subprocess_tries = 2;
260 self->state.opts.subprocess_wait_between_tries = 1;
261 self->state.opts.max_tries = 5;
262 self->timeout.tv_sec = 2;
263 EXPECT_EQ (0, runner (self, NULL));
264 self->state.tries = 0;
265 args[0] = "src/test/check-host-2";
266 self->state.last_sync_type = SYNC_TYPE_NONE;
267 EXPECT_EQ (0, runner (self, NULL));
268 self->state.tries = 0;
269 args[0] = "src/test/check-host-1";
270 self->state.last_sync_type = SYNC_TYPE_NONE;
271 EXPECT_EQ (0, runner (self, NULL));
272 self->state.tries = 0;
273 args[0] = "src/test/check-host-2";
274 self->state.last_sync_type = SYNC_TYPE_NONE;
275 EXPECT_EQ (0, runner (self, NULL));
276 }
277
TEST_F(tlsdate,proxy_override)278 TEST_F (tlsdate, proxy_override)
279 {
280 struct source s1 =
281 {
282 .next = NULL,
283 .host = "host",
284 .port = "port",
285 .proxy = NULL,
286 };
287 char *args[] = { "src/test/proxy-override", NULL };
288 extern char **environ;
289 self->state.envp = environ;
290 self->state.opts.sources = &s1;
291 self->state.opts.base_argv = args;
292 self->state.opts.subprocess_tries = 2;
293 self->state.opts.subprocess_wait_between_tries = 1;
294 EXPECT_EQ (0, runner (self, NULL));
295 EXPECT_EQ (RECENT_COMPILE_DATE + 1, self->state.last_time);
296 s1.proxy = "socks5://bad.proxy";
297 self->state.tries = 0;
298 self->state.last_sync_type = SYNC_TYPE_NONE;
299 EXPECT_EQ (0, runner (self, NULL));
300 EXPECT_EQ (RECENT_COMPILE_DATE + 3, self->state.last_time);
301 self->state.opts.proxy = "socks5://good.proxy";
302 self->state.tries = 0;
303 self->state.last_sync_type = SYNC_TYPE_NONE;
304 EXPECT_EQ (0, runner (self, NULL));
305 EXPECT_EQ (RECENT_COMPILE_DATE + 2, self->state.last_time);
306 }
307
FIXTURE(mock_platform)308 FIXTURE(mock_platform) {
309 struct platform platform;
310 struct platform *old_platform;
311 };
312
FIXTURE_SETUP(mock_platform)313 FIXTURE_SETUP(mock_platform) {
314 self->old_platform = platform;
315 self->platform.rtc_open = NULL;
316 self->platform.rtc_write = NULL;
317 self->platform.rtc_read = NULL;
318 self->platform.rtc_close = NULL;
319 platform = &self->platform;
320 }
321
FIXTURE_TEARDOWN(mock_platform)322 FIXTURE_TEARDOWN(mock_platform) {
323 platform = self->old_platform;
324 }
325
326 /* TODO: leap_tests, time_setter tests. */
327
328 TEST_HARNESS_MAIN
329