aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/tests/storageserver/service_layer_error_listener_test.cpp
blob: edb13eea5aff909246ac93fb8f2329320575bddb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <tests/common/testhelper.h>
#include <tests/common/teststorageapp.h>
#include <vespa/config/helper/configgetter.hpp>
#include <vespa/storage/storageserver/mergethrottler.h>
#include <vespa/storage/storageserver/service_layer_error_listener.h>
#include <vespa/storageframework/defaultimplementation/component/componentregisterimpl.h>
#include <vespa/vdstestlib/config/dirconfig.h>
#include <vespa/vespalib/gtest/gtest.h>

using namespace ::testing;

namespace storage {

struct ServiceLayerErrorListenerTest : Test {
};

namespace {

class TestShutdownListener
    : public framework::defaultimplementation::ShutdownListener
{
public:
    TestShutdownListener() : _reason() {}

    void requestShutdown(vespalib::stringref reason) override {
        _reason = reason;
    }

    bool shutdown_requested() const { return !_reason.empty(); }
    const vespalib::string& reason() const { return _reason; }
private:
    vespalib::string _reason;
};

struct Fixture {
    using StorServerConfig = vespa::config::content::core::StorServerConfig;

    vdstestlib::DirConfig config{getStandardConfig(true)};
    TestServiceLayerApp app;
    ServiceLayerComponent component{app.getComponentRegister(), "dummy"};
    MergeThrottler merge_throttler{*config_from<StorServerConfig>(config::ConfigUri(config.getConfigId())), app.getComponentRegister()};
    TestShutdownListener shutdown_listener;
    ServiceLayerErrorListener error_listener{component, merge_throttler};

    Fixture();
    ~Fixture();
};

Fixture::Fixture() = default;
Fixture::~Fixture() = default;

}

TEST_F(ServiceLayerErrorListenerTest, shutdown_invoked_on_fatal_error) {
    Fixture f;

    f.app.getComponentRegister().registerShutdownListener(f.shutdown_listener);
    EXPECT_FALSE(f.shutdown_listener.shutdown_requested());

    f.error_listener.on_fatal_error("eject! eject!");
    EXPECT_TRUE(f.shutdown_listener.shutdown_requested());
    EXPECT_EQ("eject! eject!", f.shutdown_listener.reason());

    // Should only be invoked once
    f.error_listener.on_fatal_error("here be dragons");
    EXPECT_EQ("eject! eject!", f.shutdown_listener.reason());
}

TEST_F(ServiceLayerErrorListenerTest, merge_throttle_backpressure_invoked_on_resource_exhaustion_error) {
    Fixture f;

    EXPECT_FALSE(f.merge_throttler.backpressure_mode_active());
    f.error_listener.on_resource_exhaustion_error("buy more RAM!");
    EXPECT_TRUE(f.merge_throttler.backpressure_mode_active());
}

}