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 21 FIXTURE (tempdir) 22 { 23 char path[PATH_MAX]; 24 }; 25 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 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 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 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 71 TEST (sane_time) 72 { 73 ASSERT_EQ (0, is_sane_time (0)); 74 ASSERT_EQ (0, is_sane_time (INT_MAX)); 75 } 76 77 TEST (sane_host_time) 78 { 79 ASSERT_EQ (1, is_sane_time (time (NULL))); 80 } 81 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 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 118 FIXTURE (tlsdate) 119 { 120 struct state state; 121 struct timeval timeout; 122 }; 123 124 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 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 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 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 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 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 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 308 FIXTURE(mock_platform) { 309 struct platform platform; 310 struct platform *old_platform; 311 }; 312 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 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