summaryrefslogtreecommitdiffstats
path: root/storage/src/tests/persistence/provider_error_wrapper_test.cpp
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@yahoo-inc.com>2017-08-31 12:06:53 +0000
committerTor Brede Vekterli <vekterli@yahoo-inc.com>2017-08-31 15:22:15 +0000
commitbd2827d46947646a538e256a4e656c8f94438917 (patch)
treedbaad465b045df560188cb94718b54d280dfe9ad /storage/src/tests/persistence/provider_error_wrapper_test.cpp
parent239ccaca10f97e9e4038ae48604e248e14074eb3 (diff)
Wire together new listener to propagate errors
Diffstat (limited to 'storage/src/tests/persistence/provider_error_wrapper_test.cpp')
-rw-r--r--storage/src/tests/persistence/provider_error_wrapper_test.cpp141
1 files changed, 141 insertions, 0 deletions
diff --git a/storage/src/tests/persistence/provider_error_wrapper_test.cpp b/storage/src/tests/persistence/provider_error_wrapper_test.cpp
new file mode 100644
index 00000000000..94a2586f0d8
--- /dev/null
+++ b/storage/src/tests/persistence/provider_error_wrapper_test.cpp
@@ -0,0 +1,141 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/vdstestlib/cppunit/macros.h>
+#include <tests/persistence/persistencetestutils.h>
+#include <tests/persistence/common/persistenceproviderwrapper.h>
+
+namespace storage {
+
+class ProviderErrorWrapperTest : public SingleDiskPersistenceTestUtils {
+public:
+ CPPUNIT_TEST_SUITE(ProviderErrorWrapperTest);
+ CPPUNIT_TEST(fatal_error_invokes_listener);
+ CPPUNIT_TEST(resource_exhaustion_error_invokes_listener);
+ CPPUNIT_TEST(listener_not_invoked_on_success);
+ CPPUNIT_TEST(listener_not_invoked_on_regular_errors);
+ CPPUNIT_TEST(multiple_listeners_can_be_registered);
+ CPPUNIT_TEST_SUITE_END();
+
+ void fatal_error_invokes_listener();
+ void resource_exhaustion_error_invokes_listener();
+ void listener_not_invoked_on_success();
+ void listener_not_invoked_on_regular_errors();
+ void multiple_listeners_can_be_registered();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ProviderErrorWrapperTest);
+
+namespace {
+
+struct MockErrorListener : ProviderErrorListener {
+ void on_fatal_error(vespalib::stringref message) override {
+ _seen_fatal_error = true;
+ _fatal_error = message;
+ }
+ void on_resource_exhaustion_error(vespalib::stringref message) override {
+ _seen_resource_exhaustion_error = true;
+ _resource_exhaustion_error = message;
+ }
+
+ vespalib::string _fatal_error;
+ vespalib::string _resource_exhaustion_error;
+ bool _seen_fatal_error{false};
+ bool _seen_resource_exhaustion_error{false};
+};
+
+struct Fixture {
+ // We wrap the wrapper. It's turtles all the way down!
+ PersistenceProviderWrapper providerWrapper;
+ TestServiceLayerApp app;
+ ServiceLayerComponent component;
+ ProviderErrorWrapper errorWrapper;
+
+ Fixture(spi::PersistenceProvider& provider)
+ : providerWrapper(provider),
+ app(),
+ component(app.getComponentRegister(), "dummy"),
+ errorWrapper(providerWrapper)
+ {
+ providerWrapper.setFailureMask(PersistenceProviderWrapper::FAIL_ALL_OPERATIONS);
+ }
+ ~Fixture() {}
+
+ void perform_spi_operation() {
+ errorWrapper.getBucketInfo(spi::Bucket(document::BucketId(16, 1234), spi::PartitionId(0)));
+ }
+};
+
+}
+
+void ProviderErrorWrapperTest::fatal_error_invokes_listener() {
+ Fixture f(getPersistenceProvider());
+ auto listener = std::make_shared<MockErrorListener>();
+ f.errorWrapper.register_error_listener(listener);
+ f.providerWrapper.setResult(spi::Result(spi::Result::FATAL_ERROR, "eject! eject!"));
+
+ CPPUNIT_ASSERT(!listener->_seen_fatal_error);
+ f.perform_spi_operation();
+
+ CPPUNIT_ASSERT(!listener->_seen_resource_exhaustion_error);
+ CPPUNIT_ASSERT(listener->_seen_fatal_error);
+ CPPUNIT_ASSERT_EQUAL(vespalib::string("eject! eject!"), listener->_fatal_error);
+}
+
+void ProviderErrorWrapperTest::resource_exhaustion_error_invokes_listener() {
+ Fixture f(getPersistenceProvider());
+ auto listener = std::make_shared<MockErrorListener>();
+ f.errorWrapper.register_error_listener(listener);
+ f.providerWrapper.setResult(spi::Result(spi::Result::RESOURCE_EXHAUSTED, "out of juice"));
+
+ CPPUNIT_ASSERT(!listener->_seen_resource_exhaustion_error);
+ f.perform_spi_operation();
+
+ CPPUNIT_ASSERT(!listener->_seen_fatal_error);
+ CPPUNIT_ASSERT(listener->_seen_resource_exhaustion_error);
+ CPPUNIT_ASSERT_EQUAL(vespalib::string("out of juice"), listener->_resource_exhaustion_error);
+}
+
+void ProviderErrorWrapperTest::listener_not_invoked_on_success() {
+ Fixture f(getPersistenceProvider());
+ auto listener = std::make_shared<MockErrorListener>();
+ f.errorWrapper.register_error_listener(listener);
+ f.perform_spi_operation();
+
+ CPPUNIT_ASSERT(!listener->_seen_fatal_error);
+ CPPUNIT_ASSERT(!listener->_seen_resource_exhaustion_error);
+}
+
+void ProviderErrorWrapperTest::listener_not_invoked_on_regular_errors() {
+ Fixture f(getPersistenceProvider());
+ auto listener = std::make_shared<MockErrorListener>();
+ f.errorWrapper.register_error_listener(listener);
+
+ // TODO dedupe
+ f.providerWrapper.setResult(spi::Result(spi::Result::TRANSIENT_ERROR, "beep boop"));
+ f.perform_spi_operation();
+ CPPUNIT_ASSERT(!listener->_seen_fatal_error);
+ CPPUNIT_ASSERT(!listener->_seen_resource_exhaustion_error);
+
+ f.providerWrapper.setResult(spi::Result(spi::Result::PERMANENT_ERROR, "beep boop!!"));
+ f.perform_spi_operation();
+ CPPUNIT_ASSERT(!listener->_seen_fatal_error);
+ CPPUNIT_ASSERT(!listener->_seen_resource_exhaustion_error);
+}
+
+void ProviderErrorWrapperTest::multiple_listeners_can_be_registered() {
+ Fixture f(getPersistenceProvider());
+ auto listener1 = std::make_shared<MockErrorListener>();
+ auto listener2 = std::make_shared<MockErrorListener>();
+ f.errorWrapper.register_error_listener(listener1);
+ f.errorWrapper.register_error_listener(listener2);
+
+ f.providerWrapper.setResult(spi::Result(spi::Result::RESOURCE_EXHAUSTED, "out of juice"));
+ f.perform_spi_operation();
+
+ CPPUNIT_ASSERT(listener1->_seen_resource_exhaustion_error);
+ CPPUNIT_ASSERT(listener2->_seen_resource_exhaustion_error);
+}
+
+} // ns storage
+
+