Line data Source code
1 : /* Copyright (c) 2012-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : #define REPLAYCACHE_PRIVATE
5 :
6 : #include "orconfig.h"
7 : #include "core/or/or.h"
8 : #include "feature/hs_common/replaycache.h"
9 : #include "test/test.h"
10 :
11 : static const char *test_buffer =
12 : "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed do eiusmod"
13 : " tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim"
14 : " veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea"
15 : " commodo consequat. Duis aute irure dolor in reprehenderit in voluptate"
16 : " velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint"
17 : " occaecat cupidatat non proident, sunt in culpa qui officia deserunt"
18 : " mollit anim id est laborum.";
19 :
20 : static const char *test_buffer_2 =
21 : "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis"
22 : " praesentium voluptatum deleniti atque corrupti quos dolores et quas"
23 : " molestias excepturi sint occaecati cupiditate non provident, similique"
24 : " sunt in culpa qui officia deserunt mollitia animi, id est laborum et"
25 : " dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio."
26 : " Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil"
27 : " impedit quo minus id quod maxime placeat facere possimus, omnis voluptas"
28 : " assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut"
29 : " officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates"
30 : " repudiandae sint et molestiae non recusandae. Itaque earum rerum hic"
31 : " tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias"
32 : " consequatur aut perferendis doloribus asperiores repellat.";
33 :
34 : static void
35 1 : test_replaycache_alloc(void *arg)
36 : {
37 1 : replaycache_t *r = NULL;
38 :
39 1 : (void)arg;
40 1 : r = replaycache_new(600, 300);
41 1 : tt_ptr_op(r, OP_NE, NULL);
42 :
43 1 : done:
44 1 : if (r) replaycache_free(r);
45 :
46 1 : return;
47 : }
48 :
49 : static void
50 1 : test_replaycache_badalloc(void *arg)
51 : {
52 1 : replaycache_t *r = NULL;
53 :
54 : /* Negative horizon should fail */
55 1 : (void)arg;
56 1 : r = replaycache_new(-600, 300);
57 1 : tt_ptr_op(r, OP_EQ, NULL);
58 : /* Negative interval should get adjusted to zero */
59 1 : r = replaycache_new(600, -300);
60 1 : tt_ptr_op(r, OP_NE, NULL);
61 1 : tt_int_op(r->scrub_interval,OP_EQ, 0);
62 1 : replaycache_free(r);
63 : /* Negative horizon and negative interval should still fail */
64 1 : r = replaycache_new(-600, -300);
65 1 : tt_ptr_op(r, OP_EQ, NULL);
66 :
67 1 : done:
68 1 : if (r) replaycache_free(r);
69 :
70 1 : return;
71 : }
72 :
73 : static void
74 1 : test_replaycache_free_null(void *arg)
75 : {
76 1 : (void)arg;
77 1 : replaycache_free_(NULL);
78 : /* Assert that we're here without horrible death */
79 1 : tt_assert(1);
80 :
81 1 : done:
82 1 : return;
83 : }
84 :
85 : static void
86 1 : test_replaycache_miss(void *arg)
87 : {
88 1 : replaycache_t *r = NULL;
89 1 : int result;
90 :
91 1 : (void)arg;
92 1 : r = replaycache_new(600, 300);
93 1 : tt_ptr_op(r, OP_NE, NULL);
94 :
95 1 : result =
96 1 : replaycache_add_and_test_internal(1200, r, test_buffer,
97 : strlen(test_buffer), NULL);
98 1 : tt_int_op(result,OP_EQ, 0);
99 :
100 : /* make sure a different buffer misses as well */
101 1 : result =
102 1 : replaycache_add_and_test_internal(1200, NULL, test_buffer_2,
103 : strlen(test_buffer_2), NULL);
104 1 : tt_int_op(result,OP_EQ, 0);
105 :
106 : /* poke the bad-parameter error case too */
107 1 : result =
108 1 : replaycache_add_and_test_internal(1200, NULL, test_buffer,
109 : strlen(test_buffer), NULL);
110 1 : tt_int_op(result,OP_EQ, 0);
111 :
112 1 : done:
113 1 : if (r) replaycache_free(r);
114 :
115 1 : return;
116 : }
117 :
118 : static void
119 1 : test_replaycache_hit(void *arg)
120 : {
121 1 : replaycache_t *r = NULL;
122 1 : int result;
123 :
124 1 : (void)arg;
125 1 : r = replaycache_new(600, 300);
126 1 : tt_ptr_op(r, OP_NE, NULL);
127 :
128 1 : result =
129 1 : replaycache_add_and_test_internal(1200, r, test_buffer,
130 : strlen(test_buffer), NULL);
131 1 : tt_int_op(result,OP_EQ, 0);
132 :
133 1 : result =
134 1 : replaycache_add_and_test_internal(1300, r, test_buffer,
135 : strlen(test_buffer), NULL);
136 1 : tt_int_op(result,OP_EQ, 1);
137 :
138 : /* make sure a different buffer misses then hits as well */
139 :
140 1 : result =
141 1 : replaycache_add_and_test_internal(1200, r, test_buffer_2,
142 : strlen(test_buffer_2), NULL);
143 1 : tt_int_op(result,OP_EQ, 0);
144 :
145 1 : result =
146 1 : replaycache_add_and_test_internal(1300, r, test_buffer_2,
147 : strlen(test_buffer_2), NULL);
148 1 : tt_int_op(result,OP_EQ, 1);
149 :
150 1 : done:
151 1 : if (r) replaycache_free(r);
152 :
153 1 : return;
154 : }
155 :
156 : static void
157 1 : test_replaycache_age(void *arg)
158 : {
159 1 : replaycache_t *r = NULL;
160 1 : int result;
161 :
162 1 : (void)arg;
163 1 : r = replaycache_new(600, 300);
164 1 : tt_ptr_op(r, OP_NE, NULL);
165 :
166 1 : result =
167 1 : replaycache_add_and_test_internal(1200, r, test_buffer,
168 : strlen(test_buffer), NULL);
169 1 : tt_int_op(result,OP_EQ, 0);
170 :
171 1 : result =
172 1 : replaycache_add_and_test_internal(1300, r, test_buffer,
173 : strlen(test_buffer), NULL);
174 1 : tt_int_op(result,OP_EQ, 1);
175 :
176 1 : result =
177 1 : replaycache_add_and_test_internal(3000, r, test_buffer,
178 : strlen(test_buffer), NULL);
179 1 : tt_int_op(result,OP_EQ, 0);
180 :
181 1 : done:
182 1 : if (r) replaycache_free(r);
183 :
184 1 : return;
185 : }
186 :
187 : static void
188 1 : test_replaycache_elapsed(void *arg)
189 : {
190 1 : replaycache_t *r = NULL;
191 1 : int result;
192 1 : time_t elapsed;
193 :
194 1 : (void)arg;
195 1 : r = replaycache_new(600, 300);
196 1 : tt_ptr_op(r, OP_NE, NULL);
197 :
198 1 : result =
199 1 : replaycache_add_and_test_internal(1200, r, test_buffer,
200 : strlen(test_buffer), NULL);
201 1 : tt_int_op(result,OP_EQ, 0);
202 :
203 1 : result =
204 1 : replaycache_add_and_test_internal(1300, r, test_buffer,
205 : strlen(test_buffer), &elapsed);
206 1 : tt_int_op(result,OP_EQ, 1);
207 1 : tt_int_op(elapsed,OP_EQ, 100);
208 :
209 1 : done:
210 1 : if (r) replaycache_free(r);
211 :
212 1 : return;
213 : }
214 :
215 : static void
216 1 : test_replaycache_noexpire(void *arg)
217 : {
218 1 : replaycache_t *r = NULL;
219 1 : int result;
220 :
221 1 : (void)arg;
222 1 : r = replaycache_new(0, 0);
223 1 : tt_ptr_op(r, OP_NE, NULL);
224 :
225 1 : result =
226 1 : replaycache_add_and_test_internal(1200, r, test_buffer,
227 : strlen(test_buffer), NULL);
228 1 : tt_int_op(result,OP_EQ, 0);
229 :
230 1 : result =
231 1 : replaycache_add_and_test_internal(1300, r, test_buffer,
232 : strlen(test_buffer), NULL);
233 1 : tt_int_op(result,OP_EQ, 1);
234 :
235 1 : result =
236 1 : replaycache_add_and_test_internal(3000, r, test_buffer,
237 : strlen(test_buffer), NULL);
238 1 : tt_int_op(result,OP_EQ, 1);
239 :
240 1 : done:
241 1 : if (r) replaycache_free(r);
242 :
243 1 : return;
244 : }
245 :
246 : static void
247 1 : test_replaycache_scrub(void *arg)
248 : {
249 1 : replaycache_t *r = NULL;
250 1 : int result;
251 :
252 1 : (void)arg;
253 1 : r = replaycache_new(600, 300);
254 1 : tt_ptr_op(r, OP_NE, NULL);
255 :
256 : /* Set up like in test_replaycache_hit() */
257 1 : result =
258 1 : replaycache_add_and_test_internal(100, r, test_buffer,
259 : strlen(test_buffer), NULL);
260 1 : tt_int_op(result,OP_EQ, 0);
261 :
262 1 : result =
263 1 : replaycache_add_and_test_internal(200, r, test_buffer,
264 : strlen(test_buffer), NULL);
265 1 : tt_int_op(result,OP_EQ, 1);
266 :
267 : /*
268 : * Poke a few replaycache_scrub_if_needed_internal() error cases that
269 : * can't happen through replaycache_add_and_test_internal()
270 : */
271 :
272 : /* Null cache */
273 1 : replaycache_scrub_if_needed_internal(300, NULL);
274 : /* Assert we're still here */
275 1 : tt_assert(1);
276 :
277 : /* Make sure we hit the aging-out case too */
278 1 : replaycache_scrub_if_needed_internal(1500, r);
279 : /* Assert that we aged it */
280 1 : tt_int_op(digest256map_size(r->digests_seen),OP_EQ, 0);
281 :
282 1 : done:
283 1 : if (r) replaycache_free(r);
284 :
285 1 : return;
286 : }
287 :
288 : static void
289 1 : test_replaycache_future(void *arg)
290 : {
291 1 : replaycache_t *r = NULL;
292 1 : int result;
293 1 : time_t elapsed = 0;
294 :
295 1 : (void)arg;
296 1 : r = replaycache_new(600, 300);
297 1 : tt_ptr_op(r, OP_NE, NULL);
298 :
299 : /* Set up like in test_replaycache_hit() */
300 1 : result =
301 1 : replaycache_add_and_test_internal(100, r, test_buffer,
302 : strlen(test_buffer), &elapsed);
303 1 : tt_int_op(result,OP_EQ, 0);
304 : /* elapsed should still be 0, since it wasn't written */
305 1 : tt_int_op(elapsed,OP_EQ, 0);
306 :
307 1 : result =
308 1 : replaycache_add_and_test_internal(200, r, test_buffer,
309 : strlen(test_buffer), &elapsed);
310 1 : tt_int_op(result,OP_EQ, 1);
311 : /* elapsed should be the time since the last hit */
312 1 : tt_int_op(elapsed,OP_EQ, 100);
313 :
314 : /*
315 : * Now let's turn the clock back to get coverage on the cache entry from the
316 : * future not-supposed-to-happen case.
317 : */
318 1 : result =
319 1 : replaycache_add_and_test_internal(150, r, test_buffer,
320 : strlen(test_buffer), &elapsed);
321 : /* We should still get a hit */
322 1 : tt_int_op(result,OP_EQ, 1);
323 : /* ...but it shouldn't let us see a negative elapsed time */
324 1 : tt_int_op(elapsed,OP_EQ, 0);
325 :
326 1 : done:
327 1 : if (r) replaycache_free(r);
328 :
329 1 : return;
330 : }
331 :
332 : static void
333 1 : test_replaycache_realtime(void *arg)
334 : {
335 1 : replaycache_t *r = NULL;
336 : /*
337 : * Negative so we fail if replaycache_add_test_and_elapsed() doesn't
338 : * write to elapsed.
339 : */
340 1 : time_t elapsed = -1;
341 1 : int result;
342 :
343 : /* Test the realtime as well as *_internal() entry points */
344 1 : (void)arg;
345 1 : r = replaycache_new(600, 300);
346 1 : tt_ptr_op(r, OP_NE, NULL);
347 :
348 : /* This should miss */
349 1 : result =
350 1 : replaycache_add_and_test(r, test_buffer, strlen(test_buffer));
351 1 : tt_int_op(result,OP_EQ, 0);
352 :
353 : /* This should hit */
354 1 : result =
355 1 : replaycache_add_and_test(r, test_buffer, strlen(test_buffer));
356 1 : tt_int_op(result,OP_EQ, 1);
357 :
358 : /* This should hit and return a small elapsed time */
359 1 : result =
360 1 : replaycache_add_test_and_elapsed(r, test_buffer,
361 : strlen(test_buffer), &elapsed);
362 1 : tt_int_op(result,OP_EQ, 1);
363 1 : tt_assert(elapsed >= 0);
364 1 : tt_assert(elapsed <= 5);
365 :
366 : /* Scrub it to exercise that entry point too */
367 1 : replaycache_scrub_if_needed(r);
368 :
369 1 : done:
370 1 : if (r) replaycache_free(r);
371 1 : return;
372 : }
373 :
374 : #define REPLAYCACHE_LEGACY(name) \
375 : { #name, test_replaycache_ ## name , 0, NULL, NULL }
376 :
377 : struct testcase_t replaycache_tests[] = {
378 : REPLAYCACHE_LEGACY(alloc),
379 : REPLAYCACHE_LEGACY(badalloc),
380 : REPLAYCACHE_LEGACY(free_null),
381 : REPLAYCACHE_LEGACY(miss),
382 : REPLAYCACHE_LEGACY(hit),
383 : REPLAYCACHE_LEGACY(age),
384 : REPLAYCACHE_LEGACY(elapsed),
385 : REPLAYCACHE_LEGACY(noexpire),
386 : REPLAYCACHE_LEGACY(scrub),
387 : REPLAYCACHE_LEGACY(future),
388 : REPLAYCACHE_LEGACY(realtime),
389 : END_OF_TESTCASES
390 : };
391 :
|