diff options
author | Daniel Pinto <danielpinto52@gmail.com> | 2020-06-03 22:09:42 +0100 |
---|---|---|
committer | Daniel Pinto <danielpinto52@gmail.com> | 2020-07-15 22:01:08 +0100 |
commit | 34fa2c4d0d8117b75c5c52a7c825486eb0284ae0 (patch) | |
tree | 572264180e98fe572d16a42d44f3b60fd4e9f52a /src/test | |
parent | a7226ca06e20356abb057c29416a9ad969c8d29d (diff) | |
download | tor-34fa2c4d0d8117b75c5c52a7c825486eb0284ae0.tar.gz tor-34fa2c4d0d8117b75c5c52a7c825486eb0284ae0.zip |
Add support for patterns on %include #25140
Also adds generic tor_glob function to expand globs.
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/fuzz/include.am | 2 | ||||
-rw-r--r-- | src/test/include.am | 21 | ||||
-rw-r--r-- | src/test/test_config.c | 346 | ||||
-rw-r--r-- | src/test/test_helpers.c | 83 | ||||
-rw-r--r-- | src/test/test_helpers.h | 2 | ||||
-rw-r--r-- | src/test/test_util.c | 436 |
6 files changed, 874 insertions, 16 deletions
diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index f3f7202ce2..510ff35a3c 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -11,7 +11,7 @@ FUZZING_LIBS = \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ @TOR_LIBEVENT_LIBS@ $(TOR_LIBS_CRYPTLIB) \ - @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ \ @TOR_LZMA_LIBS@ \ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@ diff --git a/src/test/include.am b/src/test/include.am index d7be1a5f77..c049053438 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -296,16 +296,15 @@ src_test_test_switch_id_LDADD = \ $(TOR_UTIL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_USERENV@ \ + @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_USERENV@ \ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@ - src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \ @TOR_LDFLAGS_libevent@ src_test_test_LDADD = \ $(TOR_INTERNAL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@ @@ -334,7 +333,7 @@ src_test_bench_LDADD = \ $(TOR_INTERNAL_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@ @@ -344,7 +343,7 @@ src_test_test_workqueue_LDADD = \ $(TOR_INTERNAL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ @TOR_TRACE_LIBS@ @@ -356,7 +355,7 @@ src_test_test_timers_LDADD = \ $(TOR_UTIL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ - $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @TOR_LZMA_LIBS@ @TOR_TRACE_LIBS@ src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS) @@ -393,7 +392,7 @@ src_test_test_ntor_cl_LDADD = \ $(TOR_INTERNAL_LIBS) \ $(rust_ldadd) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ @TOR_LZMA_LIBS@ @TOR_TRACE_LIBS@ src_test_test_ntor_cl_AM_CPPFLAGS = \ $(AM_CPPFLAGS) @@ -403,8 +402,8 @@ src_test_test_hs_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) src_test_test_hs_ntor_cl_LDADD = \ $(TOR_INTERNAL_LIBS) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ \ - @CURVE25519_LIBS@ @TOR_TRACE_LIBS@ + $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ \ + @CURVE25519_LIBS@ @TOR_TRACE_LIBS@ src_test_test_hs_ntor_cl_AM_CPPFLAGS = \ $(AM_CPPFLAGS) @@ -416,8 +415,8 @@ src_test_test_bt_cl_LDADD = \ $(TOR_UTIL_TESTING_LIBS) \ $(rust_ldadd) \ @TOR_LIB_MATH@ \ - @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ - @TOR_TRACE_LIBS@ + @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ + @TOR_TRACE_LIBS@ src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) endif diff --git a/src/test/test_config.c b/src/test/test_config.c index cdf668be49..617a52b8ac 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -5958,6 +5958,286 @@ test_config_include_flag_defaults_only(void *data) } static void +test_config_include_wildcards(void *data) +{ + (void)data; + + char *temp = NULL, *folder = NULL; + config_line_t *result = NULL; + char *dir = tor_strdup(get_fname("test_include_wildcards")); + tt_ptr_op(dir, OP_NE, NULL); + +#ifdef _WIN32 + tt_int_op(mkdir(dir), OP_EQ, 0); +#else + tt_int_op(mkdir(dir, 0700), OP_EQ, 0); +#endif + + tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", dir, "01_one.conf"); + tt_int_op(write_str_to_file(temp, "Test 1\n", 0), OP_EQ, 0); + tor_free(temp); + + tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", dir, "02_two.conf"); + tt_int_op(write_str_to_file(temp, "Test 2\n", 0), OP_EQ, 0); + tor_free(temp); + + tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", dir, "aa_three.conf"); + tt_int_op(write_str_to_file(temp, "Test 3\n", 0), OP_EQ, 0); + tor_free(temp); + + tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", dir, "foo"); + tt_int_op(write_str_to_file(temp, "Test 6\n", 0), OP_EQ, 0); + tor_free(temp); + + tor_asprintf(&folder, "%s"PATH_SEPARATOR"%s", dir, "folder"); + +#ifdef _WIN32 + tt_int_op(mkdir(folder), OP_EQ, 0); +#else + tt_int_op(mkdir(folder, 0700), OP_EQ, 0); +#endif + + tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", folder, "04_four.conf"); + tt_int_op(write_str_to_file(temp, "Test 4\n", 0), OP_EQ, 0); + tor_free(temp); + + tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", folder, "05_five.conf"); + tt_int_op(write_str_to_file(temp, "Test 5\n", 0), OP_EQ, 0); + tor_free(temp); + + char torrc_contents[1000]; + int include_used; + + // test pattern that matches no file + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR"not-exist*\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_ptr_op(result, OP_EQ, NULL); + tt_int_op(include_used, OP_EQ, 1); + config_free_lines(result); + +#ifndef _WIN32 + // test wildcard escaping + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR"\\*\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, -1); + tt_ptr_op(result, OP_EQ, NULL); + tt_int_op(include_used, OP_EQ, 1); + config_free_lines(result); +#endif + + // test pattern *.conf + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR"*.conf\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + + int len = 0; + config_line_t *next; + char expected[10]; + for (next = result; next != NULL; next = next->next) { + tor_snprintf(expected, sizeof(expected), "%d", len + 1); + tt_str_op(next->key, OP_EQ, "Test"); + tt_str_op(next->value, OP_EQ, expected); + len++; + } + tt_int_op(len, OP_EQ, 3); + config_free_lines(result); + + // test pattern that matches folder and files + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR"*\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + + len = 0; + for (next = result; next != NULL; next = next->next) { + tor_snprintf(expected, sizeof(expected), "%d", len + 1); + tt_str_op(next->key, OP_EQ, "Test"); + tt_str_op(next->value, OP_EQ, expected); + len++; + } + tt_int_op(len, OP_EQ, 6); + config_free_lines(result); + + // test pattern ending in PATH_SEPARATOR, test linux path separator + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s/f*/\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + + len = 0; + for (next = result; next != NULL; next = next->next) { + tor_snprintf(expected, sizeof(expected), "%d", len + 1 + 3); + tt_str_op(next->key, OP_EQ, "Test"); + tt_str_op(next->value, OP_EQ, expected); + len++; + } + tt_int_op(len, OP_EQ, 2); + config_free_lines(result); + + // test pattern with wildcards in folder and file + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR"*"PATH_SEPARATOR"*.conf\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + + len = 0; + for (next = result; next != NULL; next = next->next) { + tor_snprintf(expected, sizeof(expected), "%d", len + 1 + 3); + tt_str_op(next->key, OP_EQ, "Test"); + tt_str_op(next->value, OP_EQ, expected); + len++; + } + tt_int_op(len, OP_EQ, 2); + config_free_lines(result); + + done: + config_free_lines(result); + tor_free(folder); + tor_free(temp); + tor_free(dir); +} + +static void +test_config_include_hidden(void *data) +{ + (void)data; + + char *temp = NULL, *folder = NULL; + config_line_t *result = NULL; + char *dir = tor_strdup(get_fname("test_include_hidden")); + tt_ptr_op(dir, OP_NE, NULL); + +#ifdef _WIN32 + tt_int_op(mkdir(dir), OP_EQ, 0); +#else + tt_int_op(mkdir(dir, 0700), OP_EQ, 0); +#endif + + tor_asprintf(&folder, "%s"PATH_SEPARATOR"%s", dir, ".dotdir"); + +#ifdef _WIN32 + tt_int_op(mkdir(folder), OP_EQ, 0); +#else + tt_int_op(mkdir(folder, 0700), OP_EQ, 0); +#endif + + tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", folder, ".dotfile"); + tt_int_op(write_str_to_file(temp, "Test 1\n", 0), OP_EQ, 0); + tor_free(temp); + + tor_asprintf(&temp, "%s"PATH_SEPARATOR"%s", folder, "file"); + tt_int_op(write_str_to_file(temp, "Test 2\n", 0), OP_EQ, 0); + tor_free(temp); + + char torrc_contents[1000]; + int include_used; + int len = 0; + config_line_t *next; + char expected[10]; + + // test wildcards do not expand to dot folders (except for windows) + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR"*\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_int_op(include_used, OP_EQ, 1); +#ifdef _WIN32 // wildcard expansion includes dot files on Windows + for (next = result; next != NULL; next = next->next) { + tor_snprintf(expected, sizeof(expected), "%d", len + 2); + tt_str_op(next->key, OP_EQ, "Test"); + tt_str_op(next->value, OP_EQ, expected); + len++; + } + tt_int_op(len, OP_EQ, 1); +#else + tt_ptr_op(result, OP_EQ, NULL); +#endif + config_free_lines(result); + + // test wildcards match hidden folders when explicitly in the pattern + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR".*\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + + len = 0; + for (next = result; next != NULL; next = next->next) { + tor_snprintf(expected, sizeof(expected), "%d", len + 2); + tt_str_op(next->key, OP_EQ, "Test"); + tt_str_op(next->value, OP_EQ, expected); + len++; + } + tt_int_op(len, OP_EQ, 1); + config_free_lines(result); + + // test hidden dir when explicitly included + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR".dotdir\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + + len = 0; + for (next = result; next != NULL; next = next->next) { + tor_snprintf(expected, sizeof(expected), "%d", len + 2); + tt_str_op(next->key, OP_EQ, "Test"); + tt_str_op(next->value, OP_EQ, expected); + len++; + } + tt_int_op(len, OP_EQ, 1); + config_free_lines(result); + + // test hidden file when explicitly included + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR".dotdir"PATH_SEPARATOR".dotfile\n", + dir); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + NULL), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + + len = 0; + for (next = result; next != NULL; next = next->next) { + tor_snprintf(expected, sizeof(expected), "%d", len + 1); + tt_str_op(next->key, OP_EQ, "Test"); + tt_str_op(next->value, OP_EQ, expected); + len++; + } + tt_int_op(len, OP_EQ, 1); + config_free_lines(result); + + done: + config_free_lines(result); + tor_free(folder); + tor_free(temp); + tor_free(dir); +} + +static void test_config_dup_and_filter(void *arg) { (void)arg; @@ -6086,7 +6366,7 @@ test_config_include_opened_file_list(void *data) smartlist_t *opened_files = smartlist_new(); char *torrcd = NULL; char *subfolder = NULL; - char *path = NULL; + char *in_subfolder = NULL; char *empty = NULL; char *file = NULL; char *dot = NULL; @@ -6115,9 +6395,9 @@ test_config_include_opened_file_list(void *data) tt_int_op(mkdir(subfolder, 0700), OP_EQ, 0); #endif - tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", subfolder, + tor_asprintf(&in_subfolder, "%s"PATH_SEPARATOR"%s", subfolder, "01_file_in_subfolder"); - tt_int_op(write_str_to_file(path, "Test 1\n", 0), OP_EQ, 0); + tt_int_op(write_str_to_file(in_subfolder, "Test 1\n", 0), OP_EQ, 0); tor_asprintf(&empty, "%s"PATH_SEPARATOR"%s", torrcd, "empty"); tt_int_op(write_str_to_file(empty, "", 0), OP_EQ, 0); @@ -6148,13 +6428,69 @@ test_config_include_opened_file_list(void *data) // dot files are not opened as we ignore them when we get their name from // their parent folder + // test with wildcards + SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f)); + smartlist_clear(opened_files); + config_free_lines(result); + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR"*\n", + torrcd); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + opened_files), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + +#ifdef _WIN32 + tt_int_op(smartlist_len(opened_files), OP_EQ, 6); +#else + tt_int_op(smartlist_len(opened_files), OP_EQ, 5); +#endif + tt_int_op(smartlist_contains_string(opened_files, torrcd), OP_EQ, 1); + tt_int_op(smartlist_contains_string(opened_files, subfolder), OP_EQ, 1); + // * will match the subfolder inside torrc.d, so it will be included + tt_int_op(smartlist_contains_string(opened_files, in_subfolder), OP_EQ, 1); + tt_int_op(smartlist_contains_string(opened_files, empty), OP_EQ, 1); + tt_int_op(smartlist_contains_string(opened_files, file), OP_EQ, 1); +#ifdef _WIN32 + // * matches the dot file on Windows + tt_int_op(smartlist_contains_string(opened_files, dot), OP_EQ, 1); +#endif + + // test with wildcards in folder and file + SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f)); + smartlist_clear(opened_files); + config_free_lines(result); + tor_snprintf(torrc_contents, sizeof(torrc_contents), + "%%include %s"PATH_SEPARATOR"*"PATH_SEPARATOR"*\n", + torrcd); + tt_int_op(config_get_lines_include(torrc_contents, &result, 0, &include_used, + opened_files), OP_EQ, 0); + tt_ptr_op(result, OP_NE, NULL); + tt_int_op(include_used, OP_EQ, 1); + +#ifdef _WIN32 + tt_int_op(smartlist_len(opened_files), OP_EQ, 6); +#else + tt_int_op(smartlist_len(opened_files), OP_EQ, 5); +#endif + tt_int_op(smartlist_contains_string(opened_files, torrcd), OP_EQ, 1); + tt_int_op(smartlist_contains_string(opened_files, subfolder), OP_EQ, 1); + tt_int_op(smartlist_contains_string(opened_files, in_subfolder), OP_EQ, 1); + // stat is called on the following files, so they count as opened + tt_int_op(smartlist_contains_string(opened_files, empty), OP_EQ, 1); + tt_int_op(smartlist_contains_string(opened_files, file), OP_EQ, 1); +#ifdef _WIN32 + // * matches the dot file on Windows + tt_int_op(smartlist_contains_string(opened_files, dot), OP_EQ, 1); +#endif + done: SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f)); smartlist_free(opened_files); config_free_lines(result); tor_free(torrcd); tor_free(subfolder); - tor_free(path); + tor_free(in_subfolder); tor_free(empty); tor_free(file); tor_free(dot); @@ -6538,6 +6874,8 @@ struct testcase_t config_tests[] = { CONFIG_TEST(include_flag_both_without, TT_FORK), CONFIG_TEST(include_flag_torrc_only, TT_FORK), CONFIG_TEST(include_flag_defaults_only, TT_FORK), + CONFIG_TEST(include_wildcards, 0), + CONFIG_TEST(include_hidden, 0), CONFIG_TEST(dup_and_filter, 0), CONFIG_TEST(check_bridge_distribution_setting_not_a_bridge, TT_FORK), CONFIG_TEST(check_bridge_distribution_setting_valid, 0), diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c index 14913b4b40..851946931c 100644 --- a/src/test/test_helpers.c +++ b/src/test/test_helpers.c @@ -47,6 +47,17 @@ #include "feature/nodelist/node_st.h" #include "feature/nodelist/routerlist_st.h" +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#ifdef _WIN32 +/* For mkdir() */ +#include <direct.h> +#else +#include <dirent.h> +#endif /* defined(_WIN32) */ + #include "test/test.h" #include "test/test_helpers.h" #include "test/test_connection.h" @@ -194,6 +205,78 @@ mock_tor_addr_lookup__fail_on_bad_addrs(const char *name, return tor_addr_lookup__real(name, family, out); } +static char * +create_directory(const char *parent_dir, const char *name) +{ + char *dir = NULL; + tor_asprintf(&dir, "%s"PATH_SEPARATOR"%s", parent_dir, name); +#ifdef _WIN32 + tt_int_op(mkdir(dir), OP_EQ, 0); +#else + tt_int_op(mkdir(dir, 0700), OP_EQ, 0); +#endif + return dir; + + done: + tor_free(dir); + return NULL; +} + +static char * +create_file(const char *parent_dir, const char *name, const char *contents) +{ + char *path = NULL; + tor_asprintf(&path, "%s"PATH_SEPARATOR"%s", parent_dir, name); + contents = contents == NULL ? "" : contents; + tt_int_op(write_str_to_file(path, contents, 0), OP_EQ, 0); + return path; + + done: + tor_free(path); + return NULL; +} + +int +create_test_directory_structure(const char *parent_dir) +{ + int ret = -1; + char *dir1 = NULL; + char *dir2 = NULL; + char *file1 = NULL; + char *file2 = NULL; + char *dot = NULL; + char *empty = NULL; + char *forbidden = NULL; + + dir1 = create_directory(parent_dir, "dir1"); + tt_assert(dir1); + dir2 = create_directory(parent_dir, "dir2"); + tt_assert(dir2); + file1 = create_file(parent_dir, "file1", "Test 1"); + tt_assert(file1); + file2 = create_file(parent_dir, "file2", "Test 2"); + tt_assert(file2); + dot = create_file(parent_dir, ".test-hidden", "Test ."); + tt_assert(dot); + empty = create_file(parent_dir, "empty", NULL); + tt_assert(empty); + forbidden = create_directory(parent_dir, "forbidden"); + tt_assert(forbidden); +#ifndef _WIN32 + tt_int_op(chmod(forbidden, 0), OP_EQ, 0); +#endif + ret = 0; + done: + tor_free(dir1); + tor_free(dir2); + tor_free(file1); + tor_free(file2); + tor_free(dot); + tor_free(empty); + tor_free(forbidden); + return ret; +} + /*********** Helper funcs for making new connections/streams *****************/ /* Helper for test_conn_get_connection() */ diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h index 66007873d1..f02ecbb0ac 100644 --- a/src/test/test_helpers.h +++ b/src/test/test_helpers.h @@ -33,6 +33,8 @@ connection_t *test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose); or_options_t *helper_parse_options(const char *conf); +int create_test_directory_structure(const char *parent_dir); + extern const char TEST_DESCRIPTORS[]; void *helper_setup_pubsub(const struct testcase_t *); diff --git a/src/test/test_util.c b/src/test/test_util.c index 2aee07a26a..4f54d45468 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -18,6 +18,7 @@ #include "lib/crypt_ops/crypto_rand.h" #include "lib/defs/time.h" #include "test/test.h" +#include "test/test_helpers.h" #include "lib/memarea/memarea.h" #include "lib/process/waitpid.h" #include "lib/process/process_win32.h" @@ -4133,6 +4134,31 @@ test_util_find_str_at_start_of_line(void *ptr) } static void +test_util_tor_strreplacechar(void *ptr) +{ + (void)ptr; + char empty[] = ""; + char not_contain[] = "bbb"; + char contains[] = "bab"; + char contains_all[] = "aaa"; + + tor_strreplacechar(empty, 'a', 'b'); + tt_str_op(empty, OP_EQ, ""); + + tor_strreplacechar(not_contain, 'a', 'b'); + tt_str_op(not_contain, OP_EQ, "bbb"); + + tor_strreplacechar(contains, 'a', 'b'); + tt_str_op(contains, OP_EQ, "bbb"); + + tor_strreplacechar(contains_all, 'a', 'b'); + tt_str_op(contains_all, OP_EQ, "bbb"); + + done: + ; +} + +static void test_util_string_is_C_identifier(void *ptr) { (void)ptr; @@ -4359,6 +4385,413 @@ test_util_listdir(void *ptr) } static void +test_util_glob(void *ptr) +{ + (void)ptr; + + smartlist_t *results = NULL; + int r, i; + char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL; + char *expected = NULL, *pattern = NULL; + // used for cleanup + char *dir1_forbidden = NULL, *dir2_forbidden = NULL; + char *forbidden_forbidden = NULL; + + dirname = tor_strdup(get_fname("test_glob")); + tt_ptr_op(dirname, OP_NE, NULL); + +#ifdef _WIN32 + r = mkdir(dirname); +#else + r = mkdir(dirname, 0700); +#endif + if (r) { + fprintf(stderr, "Can't create directory %s:", dirname); + perror(""); + exit(1); + } + + tt_int_op(0, OP_EQ, create_test_directory_structure(dirname)); + tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname); + tor_asprintf(&dir1_forbidden, + "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname); + tt_int_op(0, OP_EQ, create_test_directory_structure(dir1)); + tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname); + tor_asprintf(&dir2_forbidden, + "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname); + tt_int_op(0, OP_EQ, create_test_directory_structure(dir2)); + tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname); + tor_asprintf(&forbidden_forbidden, + "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname); +#ifndef _WIN32 + chmod(forbidden, 0700); +#endif + tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden)); +#ifndef _WIN32 + chmod(forbidden, 0); +#endif + +#define TEST(input) \ + do { \ + tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \ + results = tor_glob(pattern); \ + tor_free(pattern); \ + tt_assert(results); \ + smartlist_sort_strings(results); \ + } while (0); + +#define EXPECT(result) \ + do { \ + tt_int_op(smartlist_len(results), OP_EQ, \ + sizeof(result)/sizeof(*result)); \ + i = 0; \ + SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \ + tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \ + tt_str_op(f, OP_EQ, expected); \ + i++; \ + tor_free(expected); \ + } SMARTLIST_FOREACH_END(f); \ + SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \ + smartlist_free(results); \ + } while (0); + +#define EXPECT_EMPTY() \ + do { \ + tt_int_op(smartlist_len(results), OP_EQ, 0); \ + SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \ + smartlist_free(results); \ + } while (0); + + // wilcards at beginning + const char *results_test1[] = {"dir2", "file2"}; + TEST("*2"); + EXPECT(results_test1); + + // wildcards at end + const char *results_test2[] = {"dir1", "dir2"}; + TEST("d*"); + EXPECT(results_test2); + + // wildcards at beginning and end +#ifdef _WIN32 + // dot files are not ignored on Windows + const char *results_test3[] = {".test-hidden", "dir1", "dir2", "file1", + "file2", "forbidden"}; +#else + const char *results_test3[] = {"dir1", "dir2", "file1", "file2", + "forbidden"}; +#endif + TEST("*i*"); + EXPECT(results_test3); + + // wildcards in middle + const char *results_test4[] = {"dir1", "dir2"}; + TEST("d?r*"); + EXPECT(results_test4); + + // test file that does not exist + TEST("not-exist"); + EXPECT_EMPTY(); + + // test wildcard that matches nothing + TEST("*not-exist*"); + EXPECT_EMPTY(); + + // test path separator at end - no wildcards + const char *results_test7[] = {"dir1"}; + TEST("dir1"); + EXPECT(results_test7); + + const char *results_test8[] = {"dir1"}; + TEST("dir1"PATH_SEPARATOR); + EXPECT(results_test8); + + const char *results_test9[] = {"file1"}; + TEST("file1"); + EXPECT(results_test9); + +#if defined(__APPLE__) || defined(__darwin__) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(OpenBSD) + TEST("file1"PATH_SEPARATOR); + EXPECT_EMPTY(); +#else + const char *results_test10[] = {"file1"}; + TEST("file1"PATH_SEPARATOR); + EXPECT(results_test10); +#endif + + // test path separator at end - with wildcards and linux path separator + const char *results_test11[] = {"dir1", "dir2", "forbidden"}; + TEST("*/"); + EXPECT(results_test11); + +#ifdef _WIN32 + // dot files are not ignored on Windows + const char *results_test12[] = {".test-hidden", "dir1", "dir2", "empty", + "file1", "file2", "forbidden"}; +#else + const char *results_test12[] = {"dir1", "dir2", "empty", "file1", "file2", + "forbidden"}; +#endif + TEST("*"); + EXPECT(results_test12); + + // wildcards on folder and file and linux path separator + const char *results_test13[] = {"dir1"PATH_SEPARATOR"dir1", + "dir1"PATH_SEPARATOR"dir2", + "dir1"PATH_SEPARATOR"file1", + "dir1"PATH_SEPARATOR"file2", + "dir2"PATH_SEPARATOR"dir1", + "dir2"PATH_SEPARATOR"dir2", + "dir2"PATH_SEPARATOR"file1", + "dir2"PATH_SEPARATOR"file2"}; + TEST("?i*/?i*"); + EXPECT(results_test13); + + // wildcards on file only + const char *results_test14[] = {"dir1"PATH_SEPARATOR"dir1", + "dir1"PATH_SEPARATOR"dir2", + "dir1"PATH_SEPARATOR"file1", + "dir1"PATH_SEPARATOR"file2"}; + TEST("dir1"PATH_SEPARATOR"?i*"); + EXPECT(results_test14); + + // wildcards on folder only + const char *results_test15[] = {"dir1"PATH_SEPARATOR"file1", + "dir2"PATH_SEPARATOR"file1"}; + TEST("?i*"PATH_SEPARATOR"file1"); + EXPECT(results_test15); + + // wildcards after file name + TEST("file1"PATH_SEPARATOR"*"); + EXPECT_EMPTY(); + +#ifndef _WIN32 + // test wildcard escaping + TEST("\\*"); + EXPECT_EMPTY(); + + // test forbidden directory + tor_asprintf(&pattern, "%s"PATH_SEPARATOR"*"PATH_SEPARATOR"*", dirname); + results = tor_glob(pattern); + tor_free(pattern); + tt_assert(!results); +#endif + +#undef TEST +#undef EXPECT +#undef EXPECT_EMPTY + + done: +#ifndef _WIN32 + chmod(forbidden, 0700); + chmod(dir1_forbidden, 0700); + chmod(dir2_forbidden, 0700); + chmod(forbidden_forbidden, 0700); +#endif + tor_free(dir1); + tor_free(dir2); + tor_free(forbidden); + tor_free(dirname); + tor_free(dir1_forbidden); + tor_free(dir2_forbidden); + tor_free(forbidden_forbidden); + tor_free(expected); + tor_free(pattern); + if (results) { + SMARTLIST_FOREACH(results, char *, f, tor_free(f)); + smartlist_free(results); + } +} + +static void +test_util_get_glob_opened_files(void *ptr) +{ + (void)ptr; + + smartlist_t *results = NULL; + int r, i; + char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL; + char *expected = NULL, *pattern = NULL; + // used for cleanup + char *dir1_forbidden = NULL, *dir2_forbidden = NULL; + char *forbidden_forbidden = NULL; + + dirname = tor_strdup(get_fname("test_get_glob_opened_files")); + tt_ptr_op(dirname, OP_NE, NULL); + +#ifdef _WIN32 + r = mkdir(dirname); +#else + r = mkdir(dirname, 0700); +#endif + if (r) { + fprintf(stderr, "Can't create directory %s:", dirname); + perror(""); + exit(1); + } + + tt_int_op(0, OP_EQ, create_test_directory_structure(dirname)); + tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname); + tor_asprintf(&dir1_forbidden, + "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname); + tt_int_op(0, OP_EQ, create_test_directory_structure(dir1)); + tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname); + tor_asprintf(&dir2_forbidden, + "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname); + tt_int_op(0, OP_EQ, create_test_directory_structure(dir2)); + tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname); + tor_asprintf(&forbidden_forbidden, + "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname); +#ifndef _WIN32 + chmod(forbidden, 0700); +#endif + tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden)); +#ifndef _WIN32 + chmod(forbidden, 0); +#endif + +#define TEST(input) \ + do { \ + if (*input) { \ + tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \ + } else { /* do not add path separator if empty string */ \ + tor_asprintf(&pattern, "%s", dirname); \ + } \ + results = get_glob_opened_files(pattern); \ + tor_free(pattern); \ + tt_assert(results); \ + smartlist_sort_strings(results); \ + } while (0); + +#define EXPECT(result) \ + do { \ + tt_int_op(smartlist_len(results), OP_EQ, \ + sizeof(result)/sizeof(*result)); \ + i = 0; \ + SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \ + if (*result[i]) { \ + tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \ + } else { /* do not add path separator if empty string */ \ + tor_asprintf(&expected, "%s", dirname); \ + } \ + tt_str_op(f, OP_EQ, expected); \ + i++; \ + tor_free(expected); \ + } SMARTLIST_FOREACH_END(f); \ + SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \ + smartlist_free(results); \ + } while (0); + +#define EXPECT_EMPTY() \ + do { \ + tt_int_op(smartlist_len(results), OP_EQ, 0); \ + SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \ + smartlist_free(results); \ + } while (0); + + // all files on folder + const char *results_test1[] = {""}; // only the folder is read + TEST("*"); + EXPECT(results_test1); + + // same as before but ending in path separator + const char *results_test2[] = {""}; // only the folder is read + TEST("*"PATH_SEPARATOR); + EXPECT(results_test2); + + // wilcards in multiple path components +#ifndef _WIN32 + const char *results_test3[] = {"", "dir1", "dir2", "empty", "file1", "file2", + "forbidden"}; +#else + // dot files are not special on windows + const char *results_test3[] = {"", ".test-hidden", "dir1", "dir2", "empty", + "file1", "file2", "forbidden"}; +#endif + TEST("*"PATH_SEPARATOR"*"); + EXPECT(results_test3); + + // same as before but ending in path separator +#ifndef _WIN32 + const char *results_test4[] = {"", "dir1", "dir2", "empty", "file1", "file2", + "forbidden"}; +#else + // dot files are not special on windows + const char *results_test4[] = {"", ".test-hidden", "dir1", "dir2", "empty", + "file1", "file2", "forbidden"}; +#endif + TEST("*"PATH_SEPARATOR"*"PATH_SEPARATOR); + EXPECT(results_test4); + + // no glob - folder + TEST(""); + EXPECT_EMPTY(); + + // same as before but ending in path separator + TEST(PATH_SEPARATOR); + EXPECT_EMPTY(); + + // no glob - file + TEST("file1"); + EXPECT_EMPTY(); + + // same as before but ending in path separator and linux path separator + TEST("file1/"); + EXPECT_EMPTY(); + + // file but with wildcard after + const char *results_test9[] = {"file1"}; + TEST("file1"PATH_SEPARATOR"*"); + EXPECT(results_test9); + + // dir inside dir and linux path separator + TEST("dir1/dir1"); + EXPECT_EMPTY(); + + // same as before but ending in path separator + TEST("dir1"PATH_SEPARATOR"dir1"PATH_SEPARATOR); + EXPECT_EMPTY(); + + // no glob - empty + TEST("empty"); + EXPECT_EMPTY(); + + // same as before but ending in path separator + TEST("empty"PATH_SEPARATOR); + EXPECT_EMPTY(); + + // no glob - does not exist + TEST("not_exist"); + EXPECT_EMPTY(); + +#undef TEST +#undef EXPECT +#undef EXPECT_EMPTY + + done: +#ifndef _WIN32 + chmod(forbidden, 0700); + chmod(dir1_forbidden, 0700); + chmod(dir2_forbidden, 0700); + chmod(forbidden_forbidden, 0700); +#endif + tor_free(dir1); + tor_free(dir2); + tor_free(forbidden); + tor_free(dirname); + tor_free(dir1_forbidden); + tor_free(dir2_forbidden); + tor_free(forbidden_forbidden); + tor_free(expected); + tor_free(pattern); + if (results) { + SMARTLIST_FOREACH(results, char *, f, tor_free(f)); + smartlist_free(results); + } +} + +static void test_util_parent_dir(void *ptr) { char *cp; @@ -6520,10 +6953,13 @@ struct testcase_t util_tests[] = { UTIL_TEST(laplace, 0), UTIL_TEST(clamp_double_to_int64, 0), UTIL_TEST(find_str_at_start_of_line, 0), + UTIL_TEST(tor_strreplacechar, 0), UTIL_TEST(string_is_C_identifier, 0), UTIL_TEST(string_is_utf8, 0), UTIL_TEST(asprintf, 0), UTIL_TEST(listdir, 0), + UTIL_TEST(glob, 0), + UTIL_TEST(get_glob_opened_files, 0), UTIL_TEST(parent_dir, 0), UTIL_TEST(ftruncate, 0), UTIL_TEST(nowrap_math, 0), |