LCOV - code coverage report
Current view: top level - test - test_options_act.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 180 181 99.4 %
Date: 2021-11-24 03:28:48 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2001-2004, Roger Dingledine.
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : #define CONFIG_PRIVATE
       7             : #include "core/or/or.h"
       8             : #include "app/config/config.h"
       9             : #include "lib/encoding/confline.h"
      10             : 
      11             : #include "test/test.h"
      12             : #include "test/log_test_helpers.h"
      13             : #include "test/test_helpers.h"
      14             : 
      15             : #ifndef _WIN32
      16             : #include <sys/stat.h>
      17             : 
      18             : /**
      19             :  * Check whether fname is readable. On success set
      20             :  * *<b>is_group_readable_out</b> to as appropriate and return 0. On failure
      21             :  * return -1.
      22             :  */
      23             : static int
      24           8 : get_file_mode(const char *fname, unsigned *permissions_out)
      25             : {
      26           8 :   struct stat st;
      27           8 :   int r = stat(fname, &st);
      28           8 :   if (r < 0)
      29             :     return -1;
      30           8 :   *permissions_out = (unsigned) st.st_mode;
      31           8 :   return 0;
      32             : }
      33             : #define assert_mode(fn,mask,expected) STMT_BEGIN                 \
      34             :   unsigned mode_;                                                \
      35             :   int tmp_ = get_file_mode((fn), &mode_);                        \
      36             :   if (tmp_ < 0) {                                                \
      37             :     TT_DIE(("Couldn't stat %s: %s", (fn), strerror(errno)));     \
      38             :   }                                                              \
      39             :   if ((mode_ & (mask)) != (expected)) {                          \
      40             :     TT_DIE(("Bad mode %o on %s", mode_, (fn)));                  \
      41             :   }                                                              \
      42             :   STMT_END
      43             : #else /* defined(_WIN32) */
      44             : /* "group-readable" isn't meaningful on windows */
      45             : #define assert_mode(fn,mask,expected) STMT_NIL
      46             : #endif /* !defined(_WIN32) */
      47             : 
      48             : static or_options_t *mock_opts;
      49             : static const or_options_t *
      50          14 : mock_get_options(void)
      51             : {
      52          14 :   return mock_opts;
      53             : }
      54             : 
      55             : static void
      56           1 : test_options_act_create_dirs(void *arg)
      57             : {
      58           1 :   (void)arg;
      59           1 :   MOCK(get_options, mock_get_options);
      60           1 :   char *msg = NULL;
      61           1 :   or_options_t *opts = mock_opts = options_new();
      62             : 
      63             :   /* We're testing options_create_directories(), which assumes that
      64             :      validate_data_directories() has already been called, and all of
      65             :      KeyDirectory, DataDirectory, and CacheDirectory are set. */
      66             : 
      67             :   /* Success case 1: all directories are the default */
      68           1 :   char *fn;
      69           1 :   fn = tor_strdup(get_fname_rnd("ddir"));
      70           1 :   opts->DataDirectory = tor_strdup(fn);
      71           1 :   opts->CacheDirectory = tor_strdup(fn);
      72           1 :   tor_asprintf(&opts->KeyDirectory, "%s/keys", fn);
      73           1 :   opts->DataDirectoryGroupReadable = 1;
      74           1 :   opts->CacheDirectoryGroupReadable = -1; /* default. */
      75           1 :   int r = options_create_directories(&msg);
      76           1 :   tt_int_op(r, OP_EQ, 0);
      77           1 :   tt_ptr_op(msg, OP_EQ, NULL);
      78           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
      79           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
      80           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
      81           1 :   assert_mode(opts->DataDirectory, 0777, 0750);
      82           1 :   assert_mode(opts->KeyDirectory, 0777, 0700);
      83           1 :   tor_free(fn);
      84           1 :   tor_free(opts->KeyDirectory);
      85           1 :   or_options_free(opts);
      86             : 
      87             :   /* Success case 2: all directories are different. */
      88           1 :   opts = mock_opts = options_new();
      89           1 :   opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
      90           1 :   opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
      91           1 :   opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
      92           1 :   opts->CacheDirectoryGroupReadable = 1; // cache directory group readable
      93           1 :   r = options_create_directories(&msg);
      94           1 :   tt_int_op(r, OP_EQ, 0);
      95           1 :   tt_ptr_op(msg, OP_EQ, NULL);
      96           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
      97           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
      98           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
      99           1 :   assert_mode(opts->DataDirectory, 0777, 0700);
     100           1 :   assert_mode(opts->KeyDirectory, 0777, 0700);
     101           1 :   assert_mode(opts->CacheDirectory, 0777, 0750);
     102           1 :   tor_free(fn);
     103           1 :   or_options_free(opts);
     104             : 
     105             :   /* Success case 3: all directories are the same. */
     106           1 :   opts = mock_opts = options_new();
     107           1 :   fn = tor_strdup(get_fname_rnd("ddir"));
     108           1 :   opts->DataDirectory = tor_strdup(fn);
     109           1 :   opts->CacheDirectory = tor_strdup(fn);
     110           1 :   opts->KeyDirectory = tor_strdup(fn);
     111           1 :   opts->DataDirectoryGroupReadable = 1;
     112           1 :   opts->CacheDirectoryGroupReadable = -1; /* default. */
     113           1 :   opts->KeyDirectoryGroupReadable = -1; /* default */
     114           1 :   r = options_create_directories(&msg);
     115           1 :   tt_int_op(r, OP_EQ, 0);
     116           1 :   tt_ptr_op(msg, OP_EQ, NULL);
     117           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
     118           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
     119           1 :   tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
     120           1 :   assert_mode(opts->DataDirectory, 0777, 0750);
     121           1 :   assert_mode(opts->KeyDirectory, 0777, 0750);
     122           1 :   assert_mode(opts->CacheDirectory, 0777, 0750);
     123           1 :   tor_free(fn);
     124           1 :   or_options_free(opts);
     125             : 
     126             :   /* Failure case 1: Can't make datadir. */
     127           1 :   opts = mock_opts = options_new();
     128           1 :   opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
     129           1 :   opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
     130           1 :   opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
     131           1 :   write_str_to_file(opts->DataDirectory, "foo", 0);
     132           1 :   r = options_create_directories(&msg);
     133           1 :   tt_int_op(r, OP_LT, 0);
     134           1 :   tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
     135           1 :   or_options_free(opts);
     136           1 :   tor_free(msg);
     137             : 
     138             :   /* Failure case 2: Can't make keydir. */
     139           1 :   opts = mock_opts = options_new();
     140           1 :   opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
     141           1 :   opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
     142           1 :   opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
     143           1 :   write_str_to_file(opts->KeyDirectory, "foo", 0);
     144           1 :   r = options_create_directories(&msg);
     145           1 :   tt_int_op(r, OP_LT, 0);
     146           1 :   tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
     147           1 :   or_options_free(opts);
     148           1 :   tor_free(msg);
     149             : 
     150             :   /* Failure case 3: Can't make cachedir. */
     151           1 :   opts = mock_opts = options_new();
     152           1 :   opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
     153           1 :   opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
     154           1 :   opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
     155           1 :   write_str_to_file(opts->CacheDirectory, "foo", 0);
     156           1 :   r = options_create_directories(&msg);
     157           1 :   tt_int_op(r, OP_LT, 0);
     158           1 :   tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
     159           1 :   tor_free(fn);
     160           1 :   or_options_free(opts);
     161           1 :   tor_free(msg);
     162             : 
     163           1 :  done:
     164           1 :   UNMOCK(get_options);
     165           1 :   or_options_free(opts);
     166           1 :   mock_opts = NULL;
     167           1 :   tor_free(fn);
     168           1 :   tor_free(msg);
     169           1 : }
     170             : 
     171             : static void
     172           1 : test_options_act_log_transition(void *arg)
     173             : {
     174           1 :   (void)arg;
     175           1 :   or_options_t *opts = mock_opts = options_new();
     176           1 :   or_options_t *old_opts = NULL;
     177           1 :   opts->LogTimeGranularity = 1000;
     178           1 :   opts->SafeLogging_ = SAFELOG_SCRUB_ALL;
     179           1 :   struct log_transaction_t *lt = NULL;
     180           1 :   char *msg = NULL;
     181           1 :   MOCK(get_options, mock_get_options);
     182             : 
     183           1 :   tt_ptr_op(opts->Logs, OP_EQ, NULL);
     184           1 :   config_line_append(&opts->Logs, "Log", "notice stdout");
     185           1 :   lt = options_start_log_transaction(NULL, &msg);
     186           1 :   tt_assert(lt);
     187           1 :   tt_assert(!msg);
     188             : 
     189             :   // commit, see that there is a change.
     190           1 :   options_commit_log_transaction(lt);
     191           1 :   lt=NULL;
     192           1 :   tt_int_op(get_min_log_level(), OP_EQ, LOG_NOTICE);
     193             : 
     194             :   // Now drop to debug.
     195           1 :   old_opts = opts;
     196           1 :   opts = mock_opts = options_new();
     197           1 :   opts->LogTimeGranularity = 1000;
     198           1 :   opts->SafeLogging_ = SAFELOG_SCRUB_ALL;
     199           1 :   config_line_append(&opts->Logs, "Log", "debug stdout");
     200           1 :   lt = options_start_log_transaction(old_opts, &msg);
     201           1 :   tt_assert(lt);
     202           1 :   tt_assert(!msg);
     203             : 
     204           1 :   setup_full_capture_of_logs(LOG_NOTICE);
     205           1 :   options_commit_log_transaction(lt);
     206           1 :   lt=NULL;
     207           1 :   expect_single_log_msg_containing("may contain sensitive information");
     208           1 :   tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
     209             : 
     210             :   // Turn off SafeLogging
     211           1 :   or_options_free(old_opts);
     212           1 :   mock_clean_saved_logs();
     213           1 :   old_opts = opts;
     214           1 :   opts = mock_opts = options_new();
     215           1 :   opts->SafeLogging_ = SAFELOG_SCRUB_NONE;
     216           1 :   opts->LogTimeGranularity = 1000;
     217           1 :   config_line_append(&opts->Logs, "Log", "debug stdout");
     218           1 :   lt = options_start_log_transaction(old_opts, &msg);
     219           1 :   tt_assert(lt);
     220           1 :   tt_assert(!msg);
     221           1 :   options_commit_log_transaction(lt);
     222           1 :   lt=NULL;
     223           1 :   expect_single_log_msg_containing("may contain sensitive information");
     224           1 :   tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
     225             : 
     226             :   // Try rolling back.
     227           1 :   or_options_free(old_opts);
     228           1 :   mock_clean_saved_logs();
     229           1 :   old_opts = opts;
     230           1 :   opts = mock_opts = options_new();
     231           1 :   opts->SafeLogging_ = SAFELOG_SCRUB_NONE;
     232           1 :   opts->LogTimeGranularity = 1000;
     233           1 :   config_line_append(&opts->Logs, "Log", "notice stdout");
     234           1 :   lt = options_start_log_transaction(old_opts, &msg);
     235           1 :   tt_assert(lt);
     236           1 :   tt_assert(!msg);
     237           1 :   options_rollback_log_transaction(lt);
     238           1 :   expect_no_log_entry();
     239           1 :   lt = NULL;
     240           1 :   tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
     241             : 
     242             :   // Now try some bad options.
     243           1 :   or_options_free(opts);
     244           1 :   mock_clean_saved_logs();
     245           1 :   opts = mock_opts = options_new();
     246           1 :   opts->LogTimeGranularity = 1000;
     247           1 :   config_line_append(&opts->Logs, "Log", "warn blaznert");
     248           1 :   lt = options_start_log_transaction(old_opts, &msg);
     249           1 :   tt_assert(!lt);
     250           1 :   tt_str_op(msg, OP_EQ, "Failed to init Log options. See logs for details.");
     251           1 :   expect_single_log_msg_containing("Couldn't parse");
     252           1 :   tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
     253             : 
     254           1 :  done:
     255           1 :   UNMOCK(get_options);
     256           1 :   or_options_free(opts);
     257           1 :   or_options_free(old_opts);
     258           1 :   tor_free(msg);
     259           1 :   if (lt)
     260           0 :     options_rollback_log_transaction(lt);
     261           1 :   teardown_capture_of_logs();
     262           1 : }
     263             : 
     264             : #ifndef COCCI
     265             : #define T(name) { #name, test_options_act_##name, TT_FORK, NULL, NULL }
     266             : #endif
     267             : 
     268             : struct testcase_t options_act_tests[] = {
     269             :   T(create_dirs),
     270             :   T(log_transition),
     271             :   END_OF_TESTCASES
     272             : };

Generated by: LCOV version 1.14