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
125
126
127
128
129
130
#include "lix/libutil/lru-cache.hh"
#include <gtest/gtest.h>

namespace nix {

    /* ----------------------------------------------------------------------------
     * size
     * --------------------------------------------------------------------------*/

    TEST(LRUCache, sizeOfEmptyCacheIsZero) {
        LRUCache<std::string, std::string> c(10);
        ASSERT_EQ(c.size(), 0);
    }

    TEST(LRUCache, sizeOfSingleElementCacheIsOne) {
        LRUCache<std::string, std::string> c(10);
        c.upsert("foo", "bar");
        ASSERT_EQ(c.size(), 1);
    }

    /* ----------------------------------------------------------------------------
     * upsert / get
     * --------------------------------------------------------------------------*/

    TEST(LRUCache, getFromEmptyCache) {
        LRUCache<std::string, std::string> c(10);
        auto val = c.get("x");
        ASSERT_EQ(val.has_value(), false);
    }

    TEST(LRUCache, getExistingValue) {
        LRUCache<std::string, std::string> c(10);
        c.upsert("foo", "bar");
        auto val = c.get("foo");
        ASSERT_EQ(val, "bar");
    }

    TEST(LRUCache, getNonExistingValueFromNonEmptyCache) {
        LRUCache<std::string, std::string> c(10);
        c.upsert("foo", "bar");
        auto val = c.get("another");
        ASSERT_EQ(val.has_value(), false);
    }

    TEST(LRUCache, upsertOnZeroCapacityCache) {
        LRUCache<std::string, std::string> c(0);
        c.upsert("foo", "bar");
        auto val = c.get("foo");
        ASSERT_EQ(val.has_value(), false);
    }

    TEST(LRUCache, updateExistingValue) {
        LRUCache<std::string, std::string> c(1);
        c.upsert("foo", "bar");

        auto val = c.get("foo");
        ASSERT_EQ(val.value_or("error"), "bar");
        ASSERT_EQ(c.size(), 1);

        c.upsert("foo", "changed");
        val = c.get("foo");
        ASSERT_EQ(val.value_or("error"), "changed");
        ASSERT_EQ(c.size(), 1);
    }

    TEST(LRUCache, overwriteOldestWhenCapacityIsReached) {
        LRUCache<std::string, std::string> c(3);
        c.upsert("one", "eins");
        c.upsert("two", "zwei");
        c.upsert("three", "drei");

        ASSERT_EQ(c.size(), 3);
        ASSERT_EQ(c.get("one").value_or("error"), "eins");

        // exceed capacity
        c.upsert("another", "whatever");

        ASSERT_EQ(c.size(), 3);
        // Retrieving "one" makes it the most recent element thus
        // two will be the oldest one and thus replaced.
        ASSERT_EQ(c.get("two").has_value(), false);
        ASSERT_EQ(c.get("another").value(), "whatever");
    }

    /* ----------------------------------------------------------------------------
     * clear
     * --------------------------------------------------------------------------*/

    TEST(LRUCache, clearEmptyCache) {
        LRUCache<std::string, std::string> c(10);
        c.clear();
        ASSERT_EQ(c.size(), 0);
    }

    TEST(LRUCache, clearNonEmptyCache) {
        LRUCache<std::string, std::string> c(10);
        c.upsert("one", "eins");
        c.upsert("two", "zwei");
        c.upsert("three", "drei");
        ASSERT_EQ(c.size(), 3);
        c.clear();
        ASSERT_EQ(c.size(), 0);
    }

    /* ----------------------------------------------------------------------------
     * erase
     * --------------------------------------------------------------------------*/

    TEST(LRUCache, eraseFromEmptyCache) {
        LRUCache<std::string, std::string> c(10);
        ASSERT_EQ(c.erase("foo"), false);
        ASSERT_EQ(c.size(), 0);
    }

    TEST(LRUCache, eraseMissingFromNonEmptyCache) {
        LRUCache<std::string, std::string> c(10);
        c.upsert("one", "eins");
        ASSERT_EQ(c.erase("foo"), false);
        ASSERT_EQ(c.size(), 1);
        ASSERT_EQ(c.get("one").value_or("error"), "eins");
    }

    TEST(LRUCache, eraseFromNonEmptyCache) {
        LRUCache<std::string, std::string> c(10);
        c.upsert("one", "eins");
        ASSERT_EQ(c.erase("one"), true);
        ASSERT_EQ(c.size(), 0);
        ASSERT_EQ(c.get("one").value_or("empty"), "empty");
    }
}