summaryrefslogtreecommitdiffstats
path: root/staging_vespalib
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2018-12-06 21:04:05 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2018-12-06 21:04:05 +0000
commitc6011003d7866f62488a638a99c501b90efe7170 (patch)
treebbe94a51b61f9d8370696ebfc407a2d8051fff78 /staging_vespalib
parentdfe58ec7ebb45281e994c54bced22c7add9c47de (diff)
Allow asserts that rember if they have been triggered before.
Diffstat (limited to 'staging_vespalib')
-rw-r--r--staging_vespalib/CMakeLists.txt1
-rw-r--r--staging_vespalib/src/tests/assert/.gitignore1
-rw-r--r--staging_vespalib/src/tests/assert/CMakeLists.txt16
-rw-r--r--staging_vespalib/src/tests/assert/assert_test.cpp30
-rw-r--r--staging_vespalib/src/tests/assert/asserter.cpp16
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt1
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/assert.cpp60
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/assert.h31
8 files changed, 156 insertions, 0 deletions
diff --git a/staging_vespalib/CMakeLists.txt b/staging_vespalib/CMakeLists.txt
index 095caf17a56..b95b4fda01f 100644
--- a/staging_vespalib/CMakeLists.txt
+++ b/staging_vespalib/CMakeLists.txt
@@ -9,6 +9,7 @@ vespa_define_module(
TESTS
src/tests/array
+ src/tests/assert
src/tests/benchmark
src/tests/bits
src/tests/clock
diff --git a/staging_vespalib/src/tests/assert/.gitignore b/staging_vespalib/src/tests/assert/.gitignore
new file mode 100644
index 00000000000..d0e23fcd846
--- /dev/null
+++ b/staging_vespalib/src/tests/assert/.gitignore
@@ -0,0 +1 @@
+staging_vespalib_asserter_app
diff --git a/staging_vespalib/src/tests/assert/CMakeLists.txt b/staging_vespalib/src/tests/assert/CMakeLists.txt
new file mode 100644
index 00000000000..88030680cfb
--- /dev/null
+++ b/staging_vespalib/src/tests/assert/CMakeLists.txt
@@ -0,0 +1,16 @@
+# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+vespa_add_executable(staging_vespalib_assert_test_app TEST
+ SOURCES
+ assert_test.cpp
+ DEPENDS
+ staging_vespalib
+)
+vespa_add_test(NAME staging_vespalib_assert_test_app COMMAND staging_vespalib_assert_test_app)
+
+vespa_add_executable(staging_vespalib_asserter_app TEST
+ SOURCES
+ asserter.cpp
+ DEPENDS
+ staging_vespalib
+)
diff --git a/staging_vespalib/src/tests/assert/assert_test.cpp b/staging_vespalib/src/tests/assert/assert_test.cpp
new file mode 100644
index 00000000000..d1a27fbf73c
--- /dev/null
+++ b/staging_vespalib/src/tests/assert/assert_test.cpp
@@ -0,0 +1,30 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/util/slaveproc.h>
+#include <vespa/vespalib/util/stringfmt.h>
+#include <vespa/fastos/file.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <vespa/defaults.h>
+
+using namespace vespalib;
+
+TEST("that it borks the first time.") {
+ vespalib::string assertName = make_string("tmp/myassert.assert.%s", vespa::Defaults::vespaUser());
+ FastOS_File::EmptyAndRemoveDirectory("tmp");
+ ASSERT_EQUAL(0, mkdir("tmp", 0755));
+ {
+ SlaveProc proc("ulimit -c 0 && exec env VESPA_HOME=./ ./staging_vespalib_asserter_app myassert 10000");
+ proc.wait();
+ ASSERT_EQUAL(proc.getExitCode() & 0x7f, 6);
+ }
+ {
+ SlaveProc proc("ulimit -c 0 && exec env VESPA_HOME=./ ./staging_vespalib_asserter_app myassert 10000");
+ proc.wait();
+ ASSERT_EQUAL(proc.getExitCode() & 0x7f, 0);
+ }
+ ASSERT_EQUAL(0, unlink(assertName.c_str()));
+ ASSERT_EQUAL(0, rmdir("tmp"));
+}
+
+TEST_MAIN_WITH_PROCESS_PROXY() { TEST_RUN_ALL(); }
diff --git a/staging_vespalib/src/tests/assert/asserter.cpp b/staging_vespalib/src/tests/assert/asserter.cpp
new file mode 100644
index 00000000000..f1be7531575
--- /dev/null
+++ b/staging_vespalib/src/tests/assert/asserter.cpp
@@ -0,0 +1,16 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/vespalib/util/assert.h>
+#include <cassert>
+#include <cstdlib>
+
+int main(int argc, char *argv[]) {
+ assert(argc == 3);
+ const char * assertKey = argv[1];
+ size_t assertCount = strtoul(argv[2], nullptr, 0);
+ for (size_t i(0); i < assertCount; i++) {
+ ASSERT_ONCE_OR_LOG(true, assertKey, 100);
+ ASSERT_ONCE_OR_LOG(false, assertKey, 100);
+ }
+ assert(assertCount == vespalib::assert::getNumAsserts(assertKey));
+ return 0;
+}
diff --git a/staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt b/staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt
index 20d47c90453..c104c047cd0 100644
--- a/staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt
+++ b/staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt
@@ -1,6 +1,7 @@
# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(staging_vespalib_vespalib_util OBJECT
SOURCES
+ assert.cpp
bits.cpp
clock.cpp
crc.cpp
diff --git a/staging_vespalib/src/vespa/vespalib/util/assert.cpp b/staging_vespalib/src/vespa/vespalib/util/assert.cpp
new file mode 100644
index 00000000000..976c227a413
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/util/assert.cpp
@@ -0,0 +1,60 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "assert.h"
+#include <vespa/defaults.h>
+
+#include <fstream>
+#include <map>
+#include <mutex>
+#include <chrono>
+#include <iomanip>
+
+#include <vespa/log/log.h>
+LOG_SETUP(".vespa.assert");
+
+namespace vespalib::assert {
+
+namespace {
+
+std::mutex _G_lock;
+std::map<std::string, size_t> _G_assertMap;
+
+}
+
+size_t getNumAsserts(const char *key)
+{
+ std::lock_guard guard(_G_lock);
+ return _G_assertMap[key];
+}
+
+void assertOnceOrLog(const char *expr, const char *key, size_t freq)
+{
+ std::string relativePath("tmp/");
+ relativePath += key;
+ relativePath += ".assert.";
+ relativePath += vespa::Defaults::vespaUser();
+ std::string rememberAssert = vespa::Defaults::underVespaHome(relativePath.c_str());
+ std::ifstream prevAssertFile(rememberAssert.c_str());
+ if (prevAssertFile) {
+ size_t count(0);
+ {
+ std::lock_guard guard(_G_lock);
+ count = _G_assertMap[key]++;
+ }
+ if ((count % freq) == 0) {
+ LOG(error,"assert(%s) named '%s' has failed %zu times", expr, key, count+1);
+ }
+ } else {
+ {
+ LOG(error, "assert(%s) named '%s' failed first time.", expr, key);
+ std::ofstream assertStream(rememberAssert.c_str());
+ std::chrono::time_point now = std::chrono::system_clock::now();
+ std::time_t now_c = std::chrono::system_clock::to_time_t(now);
+ assertStream << std::put_time(std::gmtime(&now_c), "%F %T") << " assert(" << expr << ") failed" << std::endl;
+ assertStream.close();
+ }
+ abort();
+ }
+}
+
+}
diff --git a/staging_vespalib/src/vespa/vespalib/util/assert.h b/staging_vespalib/src/vespa/vespalib/util/assert.h
new file mode 100644
index 00000000000..c59d51fb784
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/util/assert.h
@@ -0,0 +1,31 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include <cstddef>
+
+namespace vespalib::assert {
+
+/**
+ * How many times has asserts against this key failed.
+ * @param key
+ * @return
+ */
+size_t getNumAsserts(const char *key);
+
+/**
+ * If there is no record on file that this assert has failed, it will be recorded and aborted.
+ * However if there is a record of it, it will merely be logged the first and then every #freq time.
+ * @param expr that failed the assert
+ * @param key unique name of assert
+ * @param logFreq how often will a failing assert be logged.
+ */
+void assertOnceOrLog(const char *expr, const char *key, size_t logFreq);
+
+}
+
+#define ASSERT_ONCE_OR_LOG(expr, key, freq) { \
+ if ( ! (expr) ) { \
+ vespalib::assert::assertOnceOrLog(#expr, key, freq); \
+ } \
+}