fold in another changes item
[tor.git] / src / test / test_microdesc.c
bloba8171a325c233473877aebeb0543682c998dd77b
1 /* Copyright (c) 2010-2013, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #include "orconfig.h"
5 #include "or.h"
7 #include "config.h"
8 #include "microdesc.h"
10 #include "test.h"
12 #ifdef _WIN32
13 /* For mkdir() */
14 #include <direct.h>
15 #else
16 #include <dirent.h>
17 #endif
19 static const char test_md1[] =
20 "onion-key\n"
21 "-----BEGIN RSA PUBLIC KEY-----\n"
22 "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
23 "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
24 "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
25 "-----END RSA PUBLIC KEY-----\n";
27 static const char test_md2[] =
28 "onion-key\n"
29 "-----BEGIN RSA PUBLIC KEY-----\n"
30 "MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n"
31 "jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n"
32 "bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n"
33 "-----END RSA PUBLIC KEY-----\n";
35 static const char test_md3[] =
36 "@last-listed 2009-06-22\n"
37 "onion-key\n"
38 "-----BEGIN RSA PUBLIC KEY-----\n"
39 "MIGJAoGBAMH3340d4ENNGrqx7UxT+lB7x6DNUKOdPEOn4teceE11xlMyZ9TPv41c\n"
40 "qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n"
41 "KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n"
42 "-----END RSA PUBLIC KEY-----\n"
43 "p accept 1-700,800-1000\n"
44 "family nodeX nodeY nodeZ\n";
46 static void
47 test_md_cache(void *data)
49 or_options_t *options = NULL;
50 microdesc_cache_t *mc = NULL ;
51 smartlist_t *added = NULL, *wanted = NULL;
52 microdesc_t *md1, *md2, *md3;
53 char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN];
54 const char *test_md3_noannotation = strchr(test_md3, '\n')+1;
55 time_t time1, time2, time3;
56 char *fn = NULL, *s = NULL;
57 (void)data;
59 options = get_options_mutable();
60 tt_assert(options);
62 time1 = time(NULL);
63 time2 = time(NULL) - 2*24*60*60;
64 time3 = time(NULL) - 15*24*60*60;
66 /* Possibly, turn this into a test setup/cleanup pair */
67 tor_free(options->DataDirectory);
68 options->DataDirectory = tor_strdup(get_fname("md_datadir_test"));
69 #ifdef _WIN32
70 tt_int_op(0, ==, mkdir(options->DataDirectory));
71 #else
72 tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
73 #endif
75 tt_assert(!strcmpstart(test_md3_noannotation, "onion-key"));
77 crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256);
78 crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256);
79 crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation),
80 DIGEST_SHA256);
82 mc = get_microdesc_cache();
84 added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0,
85 time1, NULL);
86 tt_int_op(1, ==, smartlist_len(added));
87 md1 = smartlist_get(added, 0);
88 smartlist_free(added);
89 added = NULL;
91 wanted = smartlist_new();
92 added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
93 time2, wanted);
94 /* Should fail, since we didn't list test_md2's digest in wanted */
95 tt_int_op(0, ==, smartlist_len(added));
96 smartlist_free(added);
97 added = NULL;
99 smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN));
100 smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN));
101 added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
102 time2, wanted);
103 /* Now it can work. md2 should have been added */
104 tt_int_op(1, ==, smartlist_len(added));
105 md2 = smartlist_get(added, 0);
106 /* And it should have gotten removed from 'wanted' */
107 tt_int_op(smartlist_len(wanted), ==, 1);
108 test_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN);
109 smartlist_free(added);
110 added = NULL;
112 added = microdescs_add_to_cache(mc, test_md3, NULL,
113 SAVED_NOWHERE, 0, -1, NULL);
114 /* Must fail, since SAVED_NOWHERE precludes annotations */
115 tt_int_op(0, ==, smartlist_len(added));
116 smartlist_free(added);
117 added = NULL;
119 added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
120 SAVED_NOWHERE, 0, time3, NULL);
121 /* Now it can work */
122 tt_int_op(1, ==, smartlist_len(added));
123 md3 = smartlist_get(added, 0);
124 smartlist_free(added);
125 added = NULL;
127 /* Okay. We added 1...3. Let's poke them to see how they look, and make
128 * sure they're really in the journal. */
129 tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
130 tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
131 tt_ptr_op(md3, ==, microdesc_cache_lookup_by_digest256(mc, d3));
133 tt_int_op(md1->last_listed, ==, time1);
134 tt_int_op(md2->last_listed, ==, time2);
135 tt_int_op(md3->last_listed, ==, time3);
137 tt_int_op(md1->saved_location, ==, SAVED_IN_JOURNAL);
138 tt_int_op(md2->saved_location, ==, SAVED_IN_JOURNAL);
139 tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL);
141 tt_int_op(md1->bodylen, ==, strlen(test_md1));
142 tt_int_op(md2->bodylen, ==, strlen(test_md2));
143 tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation));
144 test_mem_op(md1->body, ==, test_md1, strlen(test_md1));
145 test_mem_op(md2->body, ==, test_md2, strlen(test_md2));
146 test_mem_op(md3->body, ==, test_md3_noannotation,
147 strlen(test_md3_noannotation));
149 tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
150 options->DataDirectory);
151 s = read_file_to_str(fn, RFTS_BIN, NULL);
152 tt_assert(s);
153 test_mem_op(md1->body, ==, s + md1->off, md1->bodylen);
154 test_mem_op(md2->body, ==, s + md2->off, md2->bodylen);
155 test_mem_op(md3->body, ==, s + md3->off, md3->bodylen);
157 tt_ptr_op(md1->family, ==, NULL);
158 tt_ptr_op(md3->family, !=, NULL);
159 tt_int_op(smartlist_len(md3->family), ==, 3);
160 tt_str_op(smartlist_get(md3->family, 0), ==, "nodeX");
162 /* Now rebuild the cache! */
163 tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
165 tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE);
166 tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE);
167 tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE);
169 /* The journal should be empty now */
170 tor_free(s);
171 s = read_file_to_str(fn, RFTS_BIN, NULL);
172 tt_str_op(s, ==, "");
173 tor_free(s);
174 tor_free(fn);
176 /* read the cache. */
177 tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
178 options->DataDirectory);
179 s = read_file_to_str(fn, RFTS_BIN, NULL);
180 test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
181 test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
182 test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
184 /* Okay, now we are going to forget about the cache entirely, and reload it
185 * from the disk. */
186 microdesc_free_all();
187 mc = get_microdesc_cache();
188 md1 = microdesc_cache_lookup_by_digest256(mc, d1);
189 md2 = microdesc_cache_lookup_by_digest256(mc, d2);
190 md3 = microdesc_cache_lookup_by_digest256(mc, d3);
191 test_assert(md1);
192 test_assert(md2);
193 test_assert(md3);
194 test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
195 test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
196 test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
198 tt_int_op(md1->last_listed, ==, time1);
199 tt_int_op(md2->last_listed, ==, time2);
200 tt_int_op(md3->last_listed, ==, time3);
202 /* Okay, now we are going to clear out everything older than a week old.
203 * In practice, that means md3 */
204 microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/);
205 tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
206 tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
207 tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
208 md3 = NULL; /* it's history now! */
210 /* rebuild again, make sure it stays gone. */
211 tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
212 tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
213 tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
214 tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
216 /* Re-add md3, and make sure we can rebuild the cache. */
217 added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
218 SAVED_NOWHERE, 0, time3, NULL);
219 tt_int_op(1, ==, smartlist_len(added));
220 md3 = smartlist_get(added, 0);
221 smartlist_free(added);
222 added = NULL;
223 tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE);
224 tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE);
225 tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL);
227 tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
228 tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE);
230 done:
231 if (options)
232 tor_free(options->DataDirectory);
233 microdesc_free_all();
235 smartlist_free(added);
236 if (wanted)
237 SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
238 smartlist_free(wanted);
239 tor_free(s);
240 tor_free(fn);
243 struct testcase_t microdesc_tests[] = {
244 { "cache", test_md_cache, TT_FORK, NULL, NULL },
245 END_OF_TESTCASES