diff options
Diffstat (limited to 'searchlib/src/tests/util/sigbushandler/sigbushandler_test.cpp')
-rw-r--r-- | searchlib/src/tests/util/sigbushandler/sigbushandler_test.cpp | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/searchlib/src/tests/util/sigbushandler/sigbushandler_test.cpp b/searchlib/src/tests/util/sigbushandler/sigbushandler_test.cpp new file mode 100644 index 00000000000..af657420575 --- /dev/null +++ b/searchlib/src/tests/util/sigbushandler/sigbushandler_test.cpp @@ -0,0 +1,131 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/fastos/fastos.h> +#include <vespa/log/log.h> +LOG_SETUP("sigbushandler_test"); +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/stllike/string.h> +#include <vespa/searchlib/util/statefile.h> +#include <vespa/searchlib/util/sigbushandler.h> +#include <atomic> +#include <iostream> +#include <fstream> +#include <string> +#include <vespa/searchlib/test/statefile.h> +#include <vespa/searchlib/test/statestring.h> + +using namespace search::test::statefile; +using namespace search::test::statestring; + +namespace search +{ + +using strvec = std::vector<vespalib::string>; + +namespace +{ + +bool +assertHistory(std::vector<vespalib::string> &exp, + std::vector<vespalib::string> &act) +{ + if (!EXPECT_EQUAL(exp.size(), act.size())) { + return false; + } + for (size_t i = 0; i < exp.size(); ++i) { + if (!EXPECT_EQUAL(exp[i], act[i])) { + return false; + } + } + return true; +} + +} + + +TEST("Test that sigbus handler can be instantated") +{ + StateFile::erase("state"); + StateFile sf("state"); + SigBusHandler sbh(&sf); + EXPECT_FALSE(sbh.fired()); +} + + +TEST("Test that sigbus handler can trap synthetic sigbus") +{ + StateFile::erase("state"); + StateFile sf("state"); + SigBusHandler sbh(&sf); + EXPECT_FALSE(sbh.fired()); + sigjmp_buf sjb; + if (sigsetjmp(sjb, 1) == 0) { + sbh.setUnwind(&sjb); + kill(getpid(), SIGBUS); + LOG(error, "Should never get here"); + abort(); + } + EXPECT_TRUE(sbh.fired()); + { + vespalib::string act = readState(sf); + normalizeTimestamp(act); + EXPECT_EQUAL("state=down ts=0.0 operation=sigbus errno=0 code=0\n", + act); + } + { + strvec exp({"state=down ts=0.0 operation=sigbus errno=0 code=0\n" }); + std::vector<vespalib::string> act(readHistory("state.history")); + normalizeTimestamps(act); + TEST_DO(assertHistory(exp, act)); + } +} + +TEST("Test that sigbus handler can trap normal sigbus") +{ + StateFile::erase("state"); + StateFile sf("state"); + SigBusHandler sbh(&sf); + EXPECT_FALSE(sbh.fired()); + + int fd = open("mmapfile", O_CREAT | O_TRUNC | O_RDWR, 0644); + assert(fd >= 0); + void *mmapres = mmap(nullptr, 4096, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + assert(mmapres != nullptr); + assert(mmapres != reinterpret_cast<void *>(-1l)); + char *p = reinterpret_cast<char *>(mmapres) + 42; + volatile char r = 0; + sigjmp_buf sjb; + if (sigsetjmp(sjb, 1) == 0) { + sbh.setUnwind(&sjb); + r = *p; + LOG(error, "Should never get here"); + abort(); + } + EXPECT_TRUE(sbh.fired()); + EXPECT_TRUE(r == '\0'); + { + vespalib::string act = readState(sf); + vespalib::string exp ="state=down ts=0.0 operation=sigbus errno=0 " + "code=2 addr=0x0000000000000000\n"; + normalizeAddr(exp, p); + normalizeTimestamp(act); + EXPECT_EQUAL(exp, act); + } + { + strvec exp({"state=down ts=0.0 operation=sigbus errno=0 code=2 " + "addr=0x0000000000000000\n" }); + normalizeAddrs(exp, p); + std::vector<vespalib::string> act(readHistory("state.history")); + normalizeTimestamps(act); + TEST_DO(assertHistory(exp, act)); + } +} + +} + +TEST_MAIN() +{ + TEST_RUN_ALL(); + search::StateFile::erase("state"); + unlink("mmapfile"); +} |