Back to index

tor  0.2.3.19-rc
test_microdesc.c
Go to the documentation of this file.
00001 /* Copyright (c) 2010-2012, The Tor Project, Inc. */
00002 /* See LICENSE for licensing information */
00003 
00004 #include "orconfig.h"
00005 #include "or.h"
00006 
00007 #include "config.h"
00008 #include "microdesc.h"
00009 
00010 #include "test.h"
00011 
00012 #ifdef _WIN32
00013 /* For mkdir() */
00014 #include <direct.h>
00015 #else
00016 #include <dirent.h>
00017 #endif
00018 
00019 static const char test_md1[] =
00020   "onion-key\n"
00021   "-----BEGIN RSA PUBLIC KEY-----\n"
00022   "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
00023   "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
00024   "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
00025   "-----END RSA PUBLIC KEY-----\n";
00026 
00027 static const char test_md2[] =
00028   "onion-key\n"
00029   "-----BEGIN RSA PUBLIC KEY-----\n"
00030   "MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n"
00031   "jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n"
00032   "bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n"
00033   "-----END RSA PUBLIC KEY-----\n";
00034 
00035 static const char test_md3[] =
00036   "@last-listed 2009-06-22\n"
00037   "onion-key\n"
00038   "-----BEGIN RSA PUBLIC KEY-----\n"
00039   "MIGJAoGBAMH3340d4ENNGrqx7UxT+lB7x6DNUKOdPEOn4teceE11xlMyZ9TPv41c\n"
00040   "qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n"
00041   "KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n"
00042   "-----END RSA PUBLIC KEY-----\n"
00043   "p accept 1-700,800-1000\n"
00044   "family nodeX nodeY nodeZ\n";
00045 
00046 static void
00047 test_md_cache(void *data)
00048 {
00049   or_options_t *options = NULL;
00050   microdesc_cache_t *mc = NULL ;
00051   smartlist_t *added = NULL, *wanted = NULL;
00052   microdesc_t *md1, *md2, *md3;
00053   char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN];
00054   const char *test_md3_noannotation = strchr(test_md3, '\n')+1;
00055   time_t time1, time2, time3;
00056   char *fn = NULL, *s = NULL;
00057   (void)data;
00058 
00059   options = get_options_mutable();
00060   tt_assert(options);
00061 
00062   time1 = time(NULL);
00063   time2 = time(NULL) - 2*24*60*60;
00064   time3 = time(NULL) - 15*24*60*60;
00065 
00066   /* Possibly, turn this into a test setup/cleanup pair */
00067   tor_free(options->DataDirectory);
00068   options->DataDirectory = tor_strdup(get_fname("md_datadir_test"));
00069 #ifdef _WIN32
00070   tt_int_op(0, ==, mkdir(options->DataDirectory));
00071 #else
00072   tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
00073 #endif
00074 
00075   tt_assert(!strcmpstart(test_md3_noannotation, "onion-key"));
00076 
00077   crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256);
00078   crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256);
00079   crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation),
00080                    DIGEST_SHA256);
00081 
00082   mc = get_microdesc_cache();
00083 
00084   added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0,
00085                                   time1, NULL);
00086   tt_int_op(1, ==, smartlist_len(added));
00087   md1 = smartlist_get(added, 0);
00088   smartlist_free(added);
00089   added = NULL;
00090 
00091   wanted = smartlist_new();
00092   added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
00093                                   time2, wanted);
00094   /* Should fail, since we didn't list test_md2's digest in wanted */
00095   tt_int_op(0, ==, smartlist_len(added));
00096   smartlist_free(added);
00097   added = NULL;
00098 
00099   smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN));
00100   smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN));
00101   added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
00102                                   time2, wanted);
00103   /* Now it can work. md2 should have been added */
00104   tt_int_op(1, ==, smartlist_len(added));
00105   md2 = smartlist_get(added, 0);
00106   /* And it should have gotten removed from 'wanted' */
00107   tt_int_op(smartlist_len(wanted), ==, 1);
00108   test_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN);
00109   smartlist_free(added);
00110   added = NULL;
00111 
00112   added = microdescs_add_to_cache(mc, test_md3, NULL,
00113                                   SAVED_NOWHERE, 0, -1, NULL);
00114   /* Must fail, since SAVED_NOWHERE precludes annotations */
00115   tt_int_op(0, ==, smartlist_len(added));
00116   smartlist_free(added);
00117   added = NULL;
00118 
00119   added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
00120                                   SAVED_NOWHERE, 0, time3, NULL);
00121   /* Now it can work */
00122   tt_int_op(1, ==, smartlist_len(added));
00123   md3 = smartlist_get(added, 0);
00124   smartlist_free(added);
00125   added = NULL;
00126 
00127   /* Okay.  We added 1...3.  Let's poke them to see how they look, and make
00128    * sure they're really in the journal. */
00129   tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
00130   tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
00131   tt_ptr_op(md3, ==, microdesc_cache_lookup_by_digest256(mc, d3));
00132 
00133   tt_int_op(md1->last_listed, ==, time1);
00134   tt_int_op(md2->last_listed, ==, time2);
00135   tt_int_op(md3->last_listed, ==, time3);
00136 
00137   tt_int_op(md1->saved_location, ==, SAVED_IN_JOURNAL);
00138   tt_int_op(md2->saved_location, ==, SAVED_IN_JOURNAL);
00139   tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL);
00140 
00141   tt_int_op(md1->bodylen, ==, strlen(test_md1));
00142   tt_int_op(md2->bodylen, ==, strlen(test_md2));
00143   tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation));
00144   test_mem_op(md1->body, ==, test_md1, strlen(test_md1));
00145   test_mem_op(md2->body, ==, test_md2, strlen(test_md2));
00146   test_mem_op(md3->body, ==, test_md3_noannotation,
00147               strlen(test_md3_noannotation));
00148 
00149   tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
00150                options->DataDirectory);
00151   s = read_file_to_str(fn, RFTS_BIN, NULL);
00152   tt_assert(s);
00153   test_mem_op(md1->body, ==, s + md1->off, md1->bodylen);
00154   test_mem_op(md2->body, ==, s + md2->off, md2->bodylen);
00155   test_mem_op(md3->body, ==, s + md3->off, md3->bodylen);
00156 
00157   tt_ptr_op(md1->family, ==, NULL);
00158   tt_ptr_op(md3->family, !=, NULL);
00159   tt_int_op(smartlist_len(md3->family), ==, 3);
00160   tt_str_op(smartlist_get(md3->family, 0), ==, "nodeX");
00161 
00162   /* Now rebuild the cache! */
00163   tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
00164 
00165   tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE);
00166   tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE);
00167   tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE);
00168 
00169   /* The journal should be empty now */
00170   tor_free(s);
00171   s = read_file_to_str(fn, RFTS_BIN, NULL);
00172   tt_str_op(s, ==, "");
00173   tor_free(s);
00174   tor_free(fn);
00175 
00176   /* read the cache. */
00177   tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
00178                options->DataDirectory);
00179   s = read_file_to_str(fn, RFTS_BIN, NULL);
00180   test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
00181   test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
00182   test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
00183 
00184   /* Okay, now we are going to forget about the cache entirely, and reload it
00185    * from the disk. */
00186   microdesc_free_all();
00187   mc = get_microdesc_cache();
00188   md1 = microdesc_cache_lookup_by_digest256(mc, d1);
00189   md2 = microdesc_cache_lookup_by_digest256(mc, d2);
00190   md3 = microdesc_cache_lookup_by_digest256(mc, d3);
00191   test_assert(md1);
00192   test_assert(md2);
00193   test_assert(md3);
00194   test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
00195   test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
00196   test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
00197 
00198   tt_int_op(md1->last_listed, ==, time1);
00199   tt_int_op(md2->last_listed, ==, time2);
00200   tt_int_op(md3->last_listed, ==, time3);
00201 
00202   /* Okay, now we are going to clear out everything older than a week old.
00203    * In practice, that means md3 */
00204   microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/);
00205   tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
00206   tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
00207   tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
00208   md3 = NULL; /* it's history now! */
00209 
00210   /* rebuild again, make sure it stays gone. */
00211   microdesc_cache_rebuild(mc, 1);
00212   tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
00213   tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
00214   tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
00215 
00216  done:
00217   if (options)
00218     tor_free(options->DataDirectory);
00219   microdesc_free_all();
00220 
00221   smartlist_free(added);
00222   if (wanted)
00223     SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
00224   smartlist_free(wanted);
00225   tor_free(s);
00226   tor_free(fn);
00227 }
00228 
00229 struct testcase_t microdesc_tests[] = {
00230   { "cache", test_md_cache, TT_FORK, NULL, NULL },
00231   END_OF_TESTCASES
00232 };
00233