summaryrefslogtreecommitdiffstats
path: root/searchcore/src/tests/proton/server/disk_mem_usage_filter/disk_mem_usage_filter_test.cpp
blob: fb0c9b1f3a9eeb32429d7c2892bdfbd95c8fe0e2 (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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/searchcore/proton/common/hw_info.h>
#include <vespa/searchcore/proton/server/disk_mem_usage_filter.h>
#include <vespa/searchcore/proton/server/resource_usage_state.h>

using namespace proton;

namespace fs = std::experimental::filesystem;

struct Fixture
{
    DiskMemUsageFilter _filter;
    using State = DiskMemUsageFilter::State;
    using Config = DiskMemUsageFilter::Config;

    Fixture()
        : _filter(HwInfo(HwInfo::Disk(100, false, false), HwInfo::Memory(1000), HwInfo::Cpu(0)))
    {
        _filter.setDiskUsedSize(20);
        _filter.setMemoryStats(vespalib::ProcessMemoryStats(297,
                                                            298,
                                                            299,
                                                            300,
                                                            42));
    }

    void testWrite(const vespalib::string &exp) {
        if (exp.empty()) {
            EXPECT_TRUE(_filter.acceptWriteOperation());
            State state = _filter.getAcceptState();
            EXPECT_TRUE(state.acceptWriteOperation());
            EXPECT_EQUAL(exp, state.message());
        } else {
            EXPECT_FALSE(_filter.acceptWriteOperation());
            State state = _filter.getAcceptState();
            EXPECT_FALSE(state.acceptWriteOperation());
            EXPECT_EQUAL(exp, state.message());
        }
    }

    void triggerDiskLimit() {
        _filter.setDiskUsedSize(90);
    }

    void triggerMemoryLimit()
    {
        _filter.setMemoryStats(vespalib::ProcessMemoryStats(897,
                                                            898,
                                                            899,
                                                            900,
                                                            43));
    }
};

TEST_F("Check that default filter allows write", Fixture)
{
    f.testWrite("");
}

TEST_F("Check that stats are wired through", Fixture)
{
    EXPECT_EQUAL(42u, f._filter.getMemoryStats().getMappingsCount());
    f.triggerMemoryLimit();
    EXPECT_EQUAL(43u, f._filter.getMemoryStats().getMappingsCount());
}

void
assertResourceUsage(double usage, double limit, double utilization, const ResourceUsageState &state)
{
    EXPECT_EQUAL(usage, state.usage());
    EXPECT_EQUAL(limit, state.limit());
    EXPECT_EQUAL(utilization, state.utilization());
}

TEST_F("Check that disk limit can be reached", Fixture)
{
    f._filter.setConfig(Fixture::Config(1.0, 0.8));
    TEST_DO(assertResourceUsage(0.2, 0.8, 0.25, f._filter.usageState().diskState()));
    f.triggerDiskLimit();
    f.testWrite("diskLimitReached: { "
                "action: \"add more content nodes\", "
                "reason: \"disk used (0.9) > disk limit (0.8)\", "
                "stats: { "
                "capacity: 100, used: 90, diskUsed: 0.9, diskLimit: 0.8}}");
    TEST_DO(assertResourceUsage(0.9, 0.8, 1.125, f._filter.usageState().diskState()));
}

TEST_F("Check that memory limit can be reached", Fixture)
{
    f._filter.setConfig(Fixture::Config(0.8, 1.0));
    TEST_DO(assertResourceUsage(0.3, 0.8, 0.375, f._filter.usageState().memoryState()));
    f.triggerMemoryLimit();
    f.testWrite("memoryLimitReached: { "
                "action: \"add more content nodes\", "
                "reason: \"memory used (0.9) > memory limit (0.8)\", "
                "stats: { "
                "mapped: { virt: 897, rss: 898}, "
                "anonymous: { virt: 899, rss: 900}, "
                "physicalMemory: 1000, memoryUsed: 0.9, memoryLimit: 0.8}}");
    TEST_DO(assertResourceUsage(0.9, 0.8, 1.125, f._filter.usageState().memoryState()));
}

TEST_F("Check that both disk limit and memory limit can be reached", Fixture)
{
    f._filter.setConfig(Fixture::Config(0.8, 0.8));
    f.triggerMemoryLimit();
    f.triggerDiskLimit();
    f.testWrite("memoryLimitReached: { "
                "action: \"add more content nodes\", "
                "reason: \"memory used (0.9) > memory limit (0.8)\", "
                "stats: { "
                "mapped: { virt: 897, rss: 898}, "
                "anonymous: { virt: 899, rss: 900}, "
                "physicalMemory: 1000, memoryUsed: 0.9, memoryLimit: 0.8}}, "
                "diskLimitReached: { "
                "action: \"add more content nodes\", "
                "reason: \"disk used (0.9) > disk limit (0.8)\", "
                "stats: { "
                "capacity: 100, used: 90, diskUsed: 0.9, diskLimit: 0.8}}");
}

TEST_MAIN() { TEST_RUN_ALL(); }