1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2016, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 extern const char tor_git_revision
[];
8 /* Ordinarily defined in tor_main.c; this bit is just here to provide one
9 * since we're not linking to tor_main.c */
10 const char tor_git_revision
[] = "";
14 * \brief Common pieces to implement unit tests.
22 #include "backtrace.h"
41 #include <openssl/crypto.h>
45 /** Temporary directory (set up by setup_directory) under which we store all
46 * our files during testing. */
47 static char temp_dir
[256];
51 static pid_t temp_dir_setup_in_pid
= 0;
53 /** Select and create the temporary directory we'll use to run our unit tests.
54 * Store it in <b>temp_dir</b>. Exit immediately if we can't create it.
59 static int is_setup
= 0;
61 char rnd
[256], rnd32
[256];
64 /* Due to base32 limitation needs to be a multiple of 5. */
65 #define RAND_PATH_BYTES 5
66 crypto_rand(rnd
, RAND_PATH_BYTES
);
67 base32_encode(rnd32
, sizeof(rnd32
), rnd
, RAND_PATH_BYTES
);
72 const char *tmp
= buf
;
73 const char *extra_backslash
= "";
74 /* If this fails, we're probably screwed anyway */
75 if (!GetTempPathA(sizeof(buf
),buf
))
76 tmp
= "c:\\windows\\temp\\";
77 if (strcmpend(tmp
, "\\")) {
78 /* According to MSDN, it should be impossible for GetTempPath to give us
79 * an answer that doesn't end with \. But let's make sure. */
80 extra_backslash
= "\\";
82 tor_snprintf(temp_dir
, sizeof(temp_dir
),
83 "%s%stor_test_%d_%s", tmp
, extra_backslash
,
84 (int)getpid(), rnd32
);
88 tor_snprintf(temp_dir
, sizeof(temp_dir
), "/tmp/tor_test_%d_%s",
89 (int) getpid(), rnd32
);
90 r
= mkdir(temp_dir
, 0700);
92 /* undo sticky bit so tests don't get confused. */
93 r
= chown(temp_dir
, getuid(), getgid());
97 fprintf(stderr
, "Can't create directory %s:", temp_dir
);
102 temp_dir_setup_in_pid
= getpid();
105 /** Return a filename relative to our testing temporary directory, based on
106 * name and suffix. If name is NULL, return the name of the testing temporary
109 get_fname_suffix(const char *name
, const char *suffix
)
111 static char buf
[1024];
115 tor_snprintf(buf
,sizeof(buf
),"%s/%s%s%s",temp_dir
,name
,suffix
? "_" : "",
116 suffix
? suffix
: "");
120 /** Return a filename relative to our testing temporary directory. If name is
121 * NULL, return the name of the testing temporary directory. */
123 get_fname(const char *name
)
125 return get_fname_suffix(name
, NULL
);
128 /** Return a filename with a random suffix, relative to our testing temporary
129 * directory. If name is NULL, return the name of the testing temporary
130 * directory, without any suffix. */
132 get_fname_rnd(const char *name
)
134 char rnd
[256], rnd32
[256];
135 crypto_rand(rnd
, RAND_PATH_BYTES
);
136 base32_encode(rnd32
, sizeof(rnd32
), rnd
, RAND_PATH_BYTES
);
137 return get_fname_suffix(name
, rnd32
);
140 /* Remove a directory and all of its subdirectories */
142 rm_rf(const char *dir
)
145 smartlist_t
*elements
;
147 elements
= tor_listdir(dir
);
149 SMARTLIST_FOREACH_BEGIN(elements
, const char *, cp
) {
151 tor_asprintf(&tmp
, "%s"PATH_SEPARATOR
"%s", dir
, cp
);
152 if (0 == stat(tmp
,&st
) && (st
.st_mode
& S_IFDIR
)) {
156 fprintf(stderr
, "Error removing %s: %s\n", tmp
, strerror(errno
));
160 } SMARTLIST_FOREACH_END(cp
);
161 SMARTLIST_FOREACH(elements
, char *, cp
, tor_free(cp
));
162 smartlist_free(elements
);
165 fprintf(stderr
, "Error removing directory %s: %s\n", dir
, strerror(errno
));
168 /** Remove all files stored under the temporary directory, and the directory
169 * itself. Called by atexit(). */
171 remove_directory(void)
173 if (getpid() != temp_dir_setup_in_pid
) {
174 /* Only clean out the tempdir when the main process is exiting. */
181 /** Define this if unit tests spend too much time generating public keys*/
182 #define CACHE_GENERATED_KEYS
184 #define N_PREGEN_KEYS 11
185 static crypto_pk_t
*pregen_keys
[N_PREGEN_KEYS
];
186 static int next_key_idx
;
188 /** Generate and return a new keypair for use in unit tests. If we're using
189 * the key cache optimization, we might reuse keys. "idx" is ignored.
190 * Our only guarantee is that we won't reuse a key till this function has been
191 * called several times. The order in which keys are returned is slightly
192 * randomized, so that tests that depend on a particular order will not be
198 #ifdef CACHE_GENERATED_KEYS
199 /* Either skip 1 or 2 keys. */
200 next_key_idx
+= crypto_rand_int_range(1,3);
201 next_key_idx
%= N_PREGEN_KEYS
;
202 return crypto_pk_dup_key(pregen_keys
[next_key_idx
]);
206 result
= crypto_pk_new();
207 res
= crypto_pk_generate_key__real(result
);
213 #ifdef CACHE_GENERATED_KEYS
215 crypto_pk_generate_key_with_bits__get_cached(crypto_pk_t
*env
, int bits
)
218 return crypto_pk_generate_key_with_bits__real(env
, bits
);
220 crypto_pk_t
*newkey
= pk_generate(0);
221 crypto_pk_assign_(env
, newkey
);
222 crypto_pk_free(newkey
);
227 /** Free all storage used for the cached key optimization. */
229 free_pregenerated_keys(void)
232 for (idx
= 0; idx
< N_PREGEN_KEYS
; ++idx
) {
233 if (pregen_keys
[idx
]) {
234 crypto_pk_free(pregen_keys
[idx
]);
235 pregen_keys
[idx
] = NULL
;
241 passthrough_test_setup(const struct testcase_t
*testcase
)
243 /* Make sure the passthrough doesn't unintentionally fail or skip tests */
244 tor_assert(testcase
->setup_data
);
245 tor_assert(testcase
->setup_data
!= (void*)TT_SKIP
);
246 return testcase
->setup_data
;
249 passthrough_test_cleanup(const struct testcase_t
*testcase
, void *ptr
)
257 ed25519_testcase_setup(const struct testcase_t
*testcase
)
259 crypto_ed25519_testing_force_impl(testcase
->setup_data
);
260 return testcase
->setup_data
;
263 ed25519_testcase_cleanup(const struct testcase_t
*testcase
, void *ptr
)
267 crypto_ed25519_testing_restore_impl();
270 const struct testcase_setup_t ed25519_test_setup
= {
271 ed25519_testcase_setup
, ed25519_testcase_cleanup
274 const struct testcase_setup_t passthrough_setup
= {
275 passthrough_test_setup
, passthrough_test_cleanup
279 an_assertion_failed(void)
281 tinytest_set_test_failed_();
284 /** Main entry point for unit test code: parse the command line, and run
285 * some unit tests. */
287 main(int c
, const char **v
)
289 or_options_t
*options
;
292 int loglevel
= LOG_ERR
;
293 int accel_crypto
= 0;
295 /* We must initialise logs before we call tor_assert() */
300 int r
= CRYPTO_set_mem_ex_functions(tor_malloc_
, tor_realloc_
, tor_free_
);
305 update_approx_time(time(NULL
));
306 options
= options_new();
313 struct tor_libevent_cfg cfg
;
314 memset(&cfg
, 0, sizeof(cfg
));
315 tor_libevent_initialize(&cfg
);
317 control_initialize_event_queue();
318 configure_backtrace_handler(get_version());
320 for (i_out
= i
= 1; i
< c
; ++i
) {
321 if (!strcmp(v
[i
], "--warn")) {
323 } else if (!strcmp(v
[i
], "--notice")) {
324 loglevel
= LOG_NOTICE
;
325 } else if (!strcmp(v
[i
], "--info")) {
327 } else if (!strcmp(v
[i
], "--debug")) {
328 loglevel
= LOG_DEBUG
;
329 } else if (!strcmp(v
[i
], "--accel")) {
338 log_severity_list_t s
;
339 memset(&s
, 0, sizeof(s
));
340 set_log_severity_config(loglevel
, LOG_ERR
, &s
);
341 /* ALWAYS log bug warnings. */
342 s
.masks
[LOG_WARN
-LOG_ERR
] |= LD_BUG
;
343 add_stream_log(&s
, "", fileno(stdout
));
346 options
->command
= CMD_RUN_UNITTESTS
;
347 if (crypto_global_init(accel_crypto
, NULL
, NULL
)) {
348 printf("Can't initialize crypto subsystem; exiting.\n");
351 crypto_set_tls_dh_prime();
352 if (crypto_seed_rng() < 0) {
353 printf("Couldn't seed RNG; exiting.\n");
358 options_init(options
);
359 options
->DataDirectory
= tor_strdup(temp_dir
);
360 options
->EntryStatistics
= 1;
361 if (set_options(options
, &errmsg
) < 0) {
362 printf("Failed to set initial options: %s\n", errmsg
);
366 tor_set_failed_assertion_callback(an_assertion_failed
);
368 #ifdef CACHE_GENERATED_KEYS
369 for (i
= 0; i
< N_PREGEN_KEYS
; ++i
) {
370 pregen_keys
[i
] = crypto_pk_new();
371 int r
= crypto_pk_generate_key(pregen_keys
[i
]);
374 MOCK(crypto_pk_generate_key_with_bits
,
375 crypto_pk_generate_key_with_bits__get_cached
);
378 atexit(remove_directory
);
380 int have_failed
= (tinytest_main(c
, v
, testgroups
) != 0);
382 free_pregenerated_keys();
385 dmalloc_log_unfreed();
387 crypto_global_cleanup();