test_options.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /* Copyright (c) 2001-2004, Roger Dingledine.
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2015, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #define CONFIG_PRIVATE
  6. #include "or.h"
  7. #include "confparse.h"
  8. #include "config.h"
  9. #include "test.h"
  10. typedef struct {
  11. int severity;
  12. uint32_t domain;
  13. char *msg;
  14. } logmsg_t;
  15. static smartlist_t *messages = NULL;
  16. static void
  17. log_cback(int severity, uint32_t domain, const char *msg)
  18. {
  19. logmsg_t *x = tor_malloc(sizeof(*x));
  20. x->severity = severity;
  21. x->domain = domain;
  22. x->msg = tor_strdup(msg);
  23. if (!messages)
  24. messages = smartlist_new();
  25. smartlist_add(messages, x);
  26. }
  27. static void
  28. setup_log_callback(void)
  29. {
  30. log_severity_list_t lst;
  31. memset(&lst, 0, sizeof(lst));
  32. lst.masks[LOG_ERR - LOG_ERR] = ~0;
  33. lst.masks[LOG_WARN - LOG_ERR] = ~0;
  34. lst.masks[LOG_NOTICE - LOG_ERR] = ~0;
  35. add_callback_log(&lst, log_cback);
  36. }
  37. static char *
  38. dump_logs(void)
  39. {
  40. smartlist_t *msgs;
  41. char *out;
  42. if (! messages)
  43. return tor_strdup("");
  44. msgs = smartlist_new();
  45. SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, x) {
  46. smartlist_add_asprintf(msgs, "[%s] %s",
  47. log_level_to_string(x->severity), x->msg);
  48. } SMARTLIST_FOREACH_END(x);
  49. out = smartlist_join_strings(msgs, "", 0, NULL);
  50. SMARTLIST_FOREACH(msgs, char *, cp, tor_free(cp));
  51. smartlist_free(msgs);
  52. return out;
  53. }
  54. static void
  55. clear_log_messages(void)
  56. {
  57. if (!messages)
  58. return;
  59. SMARTLIST_FOREACH(messages, logmsg_t *, m,
  60. { tor_free(m->msg); tor_free(m); });
  61. smartlist_free(messages);
  62. messages = NULL;
  63. }
  64. #define setup_options(opt,dflt) \
  65. do { \
  66. opt = options_new(); \
  67. opt->command = CMD_RUN_TOR; \
  68. options_init(opt); \
  69. \
  70. dflt = config_dup(&options_format, opt); \
  71. clear_log_messages(); \
  72. } while (0)
  73. static void
  74. test_options_validate_impl(const char *configuration,
  75. const char *expect_errmsg,
  76. int expect_log_severity,
  77. const char *expect_log)
  78. {
  79. or_options_t *opt=NULL;
  80. or_options_t *dflt;
  81. config_line_t *cl=NULL;
  82. char *msg=NULL;
  83. int r;
  84. setup_options(opt, dflt);
  85. r = config_get_lines(configuration, &cl, 1);
  86. tt_int_op(r, OP_EQ, 0);
  87. r = config_assign(&options_format, opt, cl, 0, 0, &msg);
  88. tt_int_op(r, OP_EQ, 0);
  89. r = options_validate(NULL, opt, dflt, 0, &msg);
  90. if (expect_errmsg && !msg) {
  91. TT_DIE(("Expected error message <%s> from <%s>, but got none.",
  92. expect_errmsg, configuration));
  93. } else if (expect_errmsg && !strstr(msg, expect_errmsg)) {
  94. TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
  95. expect_errmsg, configuration, msg));
  96. } else if (!expect_errmsg && msg) {
  97. TT_DIE(("Expected no error message from <%s> but got <%s>.",
  98. configuration, msg));
  99. }
  100. tt_int_op((r == 0), OP_EQ, (msg == NULL));
  101. if (expect_log) {
  102. int found = 0;
  103. if (messages) {
  104. SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, m) {
  105. if (m->severity == expect_log_severity &&
  106. strstr(m->msg, expect_log)) {
  107. found = 1;
  108. break;
  109. }
  110. } SMARTLIST_FOREACH_END(m);
  111. }
  112. if (!found) {
  113. tor_free(msg);
  114. msg = dump_logs();
  115. TT_DIE(("Expected log message [%s] %s from <%s>, but got <%s>.",
  116. log_level_to_string(expect_log_severity), expect_log,
  117. configuration, msg));
  118. }
  119. }
  120. done:
  121. config_free_lines(cl);
  122. or_options_free(opt);
  123. or_options_free(dflt);
  124. tor_free(msg);
  125. clear_log_messages();
  126. }
  127. #define WANT_ERR(config, msg) \
  128. test_options_validate_impl((config), (msg), 0, NULL)
  129. #define WANT_LOG(config, severity, msg) \
  130. test_options_validate_impl((config), NULL, (severity), (msg))
  131. #define WANT_ERR_LOG(config, msg, severity, logmsg) \
  132. test_options_validate_impl((config), (msg), (severity), (logmsg))
  133. #define OK(config) \
  134. test_options_validate_impl((config), NULL, 0, NULL)
  135. static void
  136. test_options_validate(void *arg)
  137. {
  138. (void)arg;
  139. setup_log_callback();
  140. WANT_ERR("ExtORPort 500000", "Invalid ExtORPort");
  141. WANT_ERR_LOG("ServerTransportOptions trebuchet",
  142. "ServerTransportOptions did not parse",
  143. LOG_WARN, "Too few arguments");
  144. OK("ServerTransportOptions trebuchet sling=snappy");
  145. OK("ServerTransportOptions trebuchet sling=");
  146. WANT_ERR_LOG("ServerTransportOptions trebuchet slingsnappy",
  147. "ServerTransportOptions did not parse",
  148. LOG_WARN, "\"slingsnappy\" is not a k=v");
  149. WANT_ERR("DirPort 8080\nDirCache 0",
  150. "DirPort configured but DirCache disabled.");
  151. WANT_ERR("BridgeRelay 1\nDirCache 0",
  152. "We're a bridge but DirCache is disabled.");
  153. clear_log_messages();
  154. return;
  155. }
  156. #define MEGABYTEIFY(mb) (U64_LITERAL(mb) << 20)
  157. static void
  158. test_have_enough_mem_for_dircache(void *arg)
  159. {
  160. (void)arg;
  161. or_options_t *opt=NULL;
  162. or_options_t *dflt;
  163. config_line_t *cl=NULL;
  164. char *msg=NULL;;
  165. int r;
  166. const char *configuration = "ORPort 8080\nDirCache 1", *expect_errmsg;
  167. setup_options(opt, dflt);
  168. setup_log_callback();
  169. (void)dflt;
  170. r = config_get_lines(configuration, &cl, 1);
  171. tt_int_op(r, OP_EQ, 0);
  172. r = config_assign(&options_format, opt, cl, 0, 0, &msg);
  173. tt_int_op(r, OP_EQ, 0);
  174. /* 300 MB RAM available, DirCache enabled */
  175. r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg);
  176. tt_int_op(r, OP_EQ, 0);
  177. tt_assert(!msg);
  178. /* 200 MB RAM available, DirCache enabled */
  179. r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg);
  180. tt_int_op(r, OP_EQ, -1);
  181. expect_errmsg = "Being a directory cache (default) with less than ";
  182. if (!strstr(msg, expect_errmsg)) {
  183. TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
  184. expect_errmsg, configuration, msg));
  185. }
  186. tor_free(msg);
  187. configuration = "ORPort 8080\nDirCache 1\nBridgeRelay 1";
  188. r = config_get_lines(configuration, &cl, 1);
  189. tt_int_op(r, OP_EQ, 0);
  190. r = config_assign(&options_format, opt, cl, 0, 0, &msg);
  191. tt_int_op(r, OP_EQ, 0);
  192. /* 300 MB RAM available, DirCache enabled, Bridge */
  193. r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg);
  194. tt_int_op(r, OP_EQ, 0);
  195. tt_assert(!msg);
  196. /* 200 MB RAM available, DirCache enabled, Bridge */
  197. r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg);
  198. tt_int_op(r, OP_EQ, -1);
  199. expect_errmsg = "Running a Bridge with less than ";
  200. if (!strstr(msg, expect_errmsg)) {
  201. TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
  202. expect_errmsg, configuration, msg));
  203. }
  204. tor_free(msg);
  205. configuration = "ORPort 8080\nDirCache 0";
  206. r = config_get_lines(configuration, &cl, 1);
  207. tt_int_op(r, OP_EQ, 0);
  208. r = config_assign(&options_format, opt, cl, 0, 0, &msg);
  209. tt_int_op(r, OP_EQ, 0);
  210. /* 200 MB RAM available, DirCache disabled */
  211. r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg);
  212. tt_int_op(r, OP_EQ, 0);
  213. tt_assert(!msg);
  214. /* 300 MB RAM available, DirCache disabled */
  215. r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg);
  216. tt_int_op(r, OP_EQ, -1);
  217. expect_errmsg = "DirCache is disabled and we are configured as a ";
  218. if (!strstr(msg, expect_errmsg)) {
  219. TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
  220. expect_errmsg, configuration, msg));
  221. }
  222. tor_free(msg);
  223. clear_log_messages();
  224. done:
  225. if (msg)
  226. tor_free(msg);
  227. tor_free(dflt);
  228. tor_free(opt);
  229. tor_free(cl);
  230. return;
  231. }
  232. struct testcase_t options_tests[] = {
  233. { "validate", test_options_validate, TT_FORK, NULL, NULL },
  234. { "mem_dircache", test_have_enough_mem_for_dircache, TT_FORK, NULL, NULL },
  235. END_OF_TESTCASES
  236. };