diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2018-12-06 21:04:05 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2018-12-06 21:04:05 +0000 |
commit | c6011003d7866f62488a638a99c501b90efe7170 (patch) | |
tree | bbe94a51b61f9d8370696ebfc407a2d8051fff78 /staging_vespalib | |
parent | dfe58ec7ebb45281e994c54bced22c7add9c47de (diff) |
Allow asserts that rember if they have been triggered before.
Diffstat (limited to 'staging_vespalib')
-rw-r--r-- | staging_vespalib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | staging_vespalib/src/tests/assert/.gitignore | 1 | ||||
-rw-r--r-- | staging_vespalib/src/tests/assert/CMakeLists.txt | 16 | ||||
-rw-r--r-- | staging_vespalib/src/tests/assert/assert_test.cpp | 30 | ||||
-rw-r--r-- | staging_vespalib/src/tests/assert/asserter.cpp | 16 | ||||
-rw-r--r-- | staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt | 1 | ||||
-rw-r--r-- | staging_vespalib/src/vespa/vespalib/util/assert.cpp | 60 | ||||
-rw-r--r-- | staging_vespalib/src/vespa/vespalib/util/assert.h | 31 |
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); \ + } \ +} |