diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /searchlib/src/tests/util/statefile |
Publish
Diffstat (limited to 'searchlib/src/tests/util/statefile')
-rw-r--r-- | searchlib/src/tests/util/statefile/.gitignore | 1 | ||||
-rw-r--r-- | searchlib/src/tests/util/statefile/CMakeLists.txt | 9 | ||||
-rw-r--r-- | searchlib/src/tests/util/statefile/DESC | 1 | ||||
-rw-r--r-- | searchlib/src/tests/util/statefile/FILES | 1 | ||||
-rw-r--r-- | searchlib/src/tests/util/statefile/statefile_test.cpp | 294 |
5 files changed, 306 insertions, 0 deletions
diff --git a/searchlib/src/tests/util/statefile/.gitignore b/searchlib/src/tests/util/statefile/.gitignore new file mode 100644 index 00000000000..504b7431a7a --- /dev/null +++ b/searchlib/src/tests/util/statefile/.gitignore @@ -0,0 +1 @@ +searchlib_statefile_test_app diff --git a/searchlib/src/tests/util/statefile/CMakeLists.txt b/searchlib/src/tests/util/statefile/CMakeLists.txt new file mode 100644 index 00000000000..b90b87fce7d --- /dev/null +++ b/searchlib/src/tests/util/statefile/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchlib_statefile_test_app + SOURCES + statefile_test.cpp + DEPENDS + searchlib_test + searchlib +) +vespa_add_test(NAME searchlib_statefile_test_app COMMAND searchlib_statefile_test_app) diff --git a/searchlib/src/tests/util/statefile/DESC b/searchlib/src/tests/util/statefile/DESC new file mode 100644 index 00000000000..6368f32bcc6 --- /dev/null +++ b/searchlib/src/tests/util/statefile/DESC @@ -0,0 +1 @@ +statefile test. Take a look at statefile_test.cpp for details. diff --git a/searchlib/src/tests/util/statefile/FILES b/searchlib/src/tests/util/statefile/FILES new file mode 100644 index 00000000000..c651bb2758f --- /dev/null +++ b/searchlib/src/tests/util/statefile/FILES @@ -0,0 +1 @@ +statefile_test.cpp diff --git a/searchlib/src/tests/util/statefile/statefile_test.cpp b/searchlib/src/tests/util/statefile/statefile_test.cpp new file mode 100644 index 00000000000..583d21e1cec --- /dev/null +++ b/searchlib/src/tests/util/statefile/statefile_test.cpp @@ -0,0 +1,294 @@ +// 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("statefile_test"); +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/stllike/string.h> +#include <vespa/searchlib/util/statefile.h> +#include <atomic> +#include <iostream> +#include <fstream> +#include <string> +#include <vespa/searchlib/test/statefile.h> + + +using namespace search::test::statefile; + +namespace search +{ + +namespace +{ + +bool +hasFile(const char *name) +{ + return access(name, R_OK | W_OK) == 0; +} + + +void +addState(StateFile &sf, const char *buf) +{ + size_t bufLen = strlen(buf); + sf.addState(buf, bufLen, false); +} + +void +addSignalState(StateFile &sf, const char *buf) +{ + size_t bufLen = strlen(buf); + sf.addState(buf, bufLen, true); +} + + +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; +} + + +int64_t +getSize(const char *name) +{ + struct stat stbuf; + if (stat(name, &stbuf) != 0) + return 0; + return stbuf.st_size; +} + + +void +setSize(const char *name, int64_t newSize) +{ + int truncRes = truncate(name, newSize); + assert(truncRes == 0); +} + + +} + + +TEST("Test lock free atomic int used by async signal safe lock primitive") +{ + std::atomic<int> f; + ASSERT_TRUE(f.is_lock_free()); +} + + +TEST("Test that statefile can be created") +{ + StateFile::erase("state"); + EXPECT_FALSE(hasFile("state")); + EXPECT_FALSE(hasFile("state.history")); + StateFile sf("state"); + EXPECT_TRUE(hasFile("state")); + EXPECT_TRUE(hasFile("state.history")); + EXPECT_EQUAL(0, sf.getGen()); + StateFile::erase("state"); + EXPECT_FALSE(hasFile("state")); + EXPECT_FALSE(hasFile("state.history")); + StateFile::erase("state"); + EXPECT_FALSE(hasFile("state")); + EXPECT_FALSE(hasFile("state.history")); +} + + +TEST("Test that statefile can add event") +{ + StateFile::erase("state"); + StateFile sf("state"); + + addState(sf, "Hello world\n"); + vespalib::string check = readState(sf); + EXPECT_EQUAL("Hello world\n", check); + EXPECT_EQUAL(1, sf.getGen()); +} + +TEST("Test that history is appended to") +{ + StateFile::erase("state"); + StateFile sf("state"); + + addState(sf, "Hello world\n"); + addState(sf, "Foo bar\n"); + vespalib::string check = readState(sf); + EXPECT_EQUAL("Foo bar\n", check); + EXPECT_EQUAL(2, sf.getGen()); + { + std::vector<vespalib::string> exp({ "Hello world\n", "Foo bar\n" }); + std::vector<vespalib::string> act(readHistory("state.history")); + TEST_DO(assertHistory(exp, act)); + } +} + + +TEST("Test that truncated history is truncated at event boundary") +{ + StateFile::erase("state"); + int64_t histSize = 1; + { + StateFile sf("state"); + addState(sf, "Hello world\n"); + addState(sf, "Foo bar\n"); + EXPECT_EQUAL(2, sf.getGen()); + histSize = getSize("state.history"); + EXPECT_EQUAL(20, histSize); + addState(sf, "zap\n"); + EXPECT_EQUAL(3, sf.getGen()); + } + // Lose 2 last events in history + setSize("state.history", histSize - 1); + // Last event is restored to history from main state file + StateFile sf("state"); + vespalib::string check = readState(sf); + EXPECT_EQUAL("zap\n", check); + EXPECT_EQUAL(0, sf.getGen()); + { + std::vector<vespalib::string> exp({ "Hello world\n", "zap\n" }); + std::vector<vespalib::string> act(readHistory("state.history")); + TEST_DO(assertHistory(exp, act)); + } +} + + +TEST("Test that async signal safe path adds event") +{ + StateFile::erase("state"); + StateFile sf("state"); + + addSignalState(sf, "Hello world\n"); + addSignalState(sf, "Foo bar\n"); + vespalib::string check = readState(sf); + EXPECT_EQUAL("Foo bar\n", check); + EXPECT_EQUAL(2, sf.getGen()); + { + std::vector<vespalib::string> exp({ "Hello world\n", "Foo bar\n" }); + std::vector<vespalib::string> act(readHistory("state.history")); + TEST_DO(assertHistory(exp, act)); + } +} + + +TEST("Test that state file can be restored from history") +{ + StateFile::erase("state"); + { + StateFile sf("state"); + addState(sf, "Hello world\n"); + addState(sf, "Foo bar\n"); + EXPECT_EQUAL(2, sf.getGen()); + } + // Lose event in main state file + setSize("state", 0); + EXPECT_EQUAL(0, getSize("state")); + // Last event is restored to history from main state file + StateFile sf("state"); + EXPECT_NOT_EQUAL(0, getSize("state")); + vespalib::string check = readState(sf); + EXPECT_EQUAL("Foo bar\n", check); + { + std::vector<vespalib::string> exp({ "Hello world\n", "Foo bar\n" }); + std::vector<vespalib::string> act(readHistory("state.history")); + TEST_DO(assertHistory(exp, act)); + } +} + + +TEST("Test that different entry is added to history") +{ + StateFile::erase("state"); + { + StateFile sf("state"); + addState(sf, "Hello world\n"); + EXPECT_EQUAL(1, sf.getGen()); + } + // Write changed entry to main state file + { + std::ofstream of("state"); + of << "zap\n"; + } + // Add changed event to history + StateFile sf("state"); + EXPECT_NOT_EQUAL(0, getSize("state")); + vespalib::string check = readState(sf); + EXPECT_EQUAL("zap\n", check); + { + std::vector<vespalib::string> exp({ "Hello world\n", "zap\n" }); + std::vector<vespalib::string> act(readHistory("state.history")); + TEST_DO(assertHistory(exp, act)); + } +} + + +TEST("Test that state history stops at NUL byte") +{ + StateFile::erase("state"); + { + StateFile sf("state"); + addState(sf, "Hello world\n"); + addState(sf, "Foo bar\n"); + EXPECT_EQUAL(2, sf.getGen()); + } + // Corrupt history state file + { + char buf[1]; + buf[0] = '\0'; + std::ofstream of("state.history"); + of.write(&buf[0], 1); + } + StateFile sf("state"); + vespalib::string check = readState(sf); + EXPECT_EQUAL("Foo bar\n", check); + { + std::vector<vespalib::string> exp({ "Foo bar\n" }); + std::vector<vespalib::string> act(readHistory("state.history")); + TEST_DO(assertHistory(exp, act)); + } + +} + +TEST("Test that main state stops at NUL byte") +{ + StateFile::erase("state"); + { + StateFile sf("state"); + addState(sf, "Hello world\n"); + addState(sf, "Foo bar\n"); + EXPECT_EQUAL(2, sf.getGen()); + } + // Corrupt history state file + { + char buf[10]; + strcpy(buf, "zap"); + std::ofstream of("state"); + of.write(&buf[0], strlen(buf) + 1); + } + StateFile sf("state"); + vespalib::string check = readState(sf); + EXPECT_EQUAL("Foo bar\n", check); + { + std::vector<vespalib::string> exp({ "Hello world\n", "Foo bar\n" }); + std::vector<vespalib::string> act(readHistory("state.history")); + TEST_DO(assertHistory(exp, act)); + } + +} + +} + +TEST_MAIN() +{ + TEST_RUN_ALL(); + search::StateFile::erase("state"); +} |