aboutsummaryrefslogtreecommitdiff
path: root/src/common/util_bug.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/util_bug.c')
-rw-r--r--src/common/util_bug.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/common/util_bug.c b/src/common/util_bug.c
index e3e1d6df90..c7bfdefe80 100644
--- a/src/common/util_bug.c
+++ b/src/common/util_bug.c
@@ -11,6 +11,54 @@
#include "util_bug.h"
#include "torlog.h"
#include "backtrace.h"
+#include "container.h"
+
+#ifdef TOR_UNIT_TESTS
+static void (*failed_assertion_cb)(void) = NULL;
+static int n_bugs_to_capture = 0;
+static smartlist_t *bug_messages = NULL;
+#define capturing_bugs() (bug_messages != NULL && n_bugs_to_capture)
+void
+tor_capture_bugs_(int n)
+{
+ tor_end_capture_bugs_();
+ bug_messages = smartlist_new();
+ n_bugs_to_capture = n;
+}
+void
+tor_end_capture_bugs_(void)
+{
+ n_bugs_to_capture = 0;
+ if (!bug_messages)
+ return;
+ SMARTLIST_FOREACH(bug_messages, char *, cp, tor_free(cp));
+ smartlist_free(bug_messages);
+ bug_messages = NULL;
+}
+const smartlist_t *
+tor_get_captured_bug_log_(void)
+{
+ return bug_messages;
+}
+static void
+add_captured_bug(const char *s)
+{
+ --n_bugs_to_capture;
+ smartlist_add_strdup(bug_messages, s);
+}
+/** Set a callback to be invoked when we get any tor_bug_occurred_
+ * invocation. We use this in the unit tests so that a nonfatal
+ * assertion failure can also count as a test failure.
+ */
+void
+tor_set_failed_assertion_callback(void (*fn)(void))
+{
+ failed_assertion_cb = fn;
+}
+#else
+#define capturing_bugs() (0)
+#define add_captured_bug(s) do { } while (0)
+#endif
/** Helper for tor_assert: report the assertion failure. */
void
@@ -36,12 +84,20 @@ tor_bug_occurred_(const char *fname, unsigned int line,
const char *once_str = once ?
" (Future instances of this warning will be silenced.)": "";
if (! expr) {
+ if (capturing_bugs()) {
+ add_captured_bug("This line should not have been reached.");
+ return;
+ }
log_warn(LD_BUG, "%s:%u: %s: This line should not have been reached.%s",
fname, line, func, once_str);
tor_snprintf(buf, sizeof(buf),
"Line unexpectedly reached at %s at %s:%u",
func, fname, line);
} else {
+ if (capturing_bugs()) {
+ add_captured_bug(expr);
+ return;
+ }
log_warn(LD_BUG, "%s:%u: %s: Non-fatal assertion %s failed.%s",
fname, line, func, expr, once_str);
tor_snprintf(buf, sizeof(buf),
@@ -49,5 +105,11 @@ tor_bug_occurred_(const char *fname, unsigned int line,
expr, func, fname, line);
}
log_backtrace(LOG_WARN, LD_BUG, buf);
+
+#ifdef TOR_UNIT_TESTS
+ if (failed_assertion_cb) {
+ failed_assertion_cb();
+ }
+#endif
}