aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/tests/stllike/hashtable_test.cpp
blob: 4948faf450f060c60b57c1e6ca42959024b7902f (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
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// Unit tests for hashtable.

#include <vespa/vespalib/stllike/hashtable.hpp>
#include <vespa/vespalib/stllike/hash_fun.h>
#include <vespa/vespalib/testkit/testapp.h>
#include <memory>
#include <vector>

using vespalib::hashtable;
using std::vector;

using namespace vespalib;

namespace {

template<typename T>
struct Dereference : std::unary_function<T, std::unique_ptr<T>> {
    T &operator()(std::unique_ptr<T>& p) const { return *p; }
    const T& operator()(const std::unique_ptr<T>& p) const { return *p; }
};

template<typename K> using up_hashtable =
    hashtable<K, std::unique_ptr<K>,
              vespalib::hash<K>, std::equal_to<K>, Dereference<K>>;

TEST("require that hashtable can store unique_ptrs") {
    up_hashtable<int> table(100);
    typedef std::unique_ptr<int> UP;
    table.insert(UP(new int(42)));
    auto it = table.find(42);
    EXPECT_EQUAL(42, **it);

    UP u = std::move(*it);  // This changes the key. Don't do this.
    EXPECT_EQUAL(42, *u);

    // it = table.find(42);  // This will crash, since the key is removed.
}

template<typename To, typename Entry>
struct First : std::unary_function<To, Entry> {
    To &operator()(Entry& p) const { return p.first; }
    const To& operator()(const Entry& p) const { return p.first; }
};

template <typename K, typename V> using Entry =
    std::pair<K, std::unique_ptr<V>>;
typedef hashtable<int, Entry<int, int>,
                  vespalib::hash<int>, std::equal_to<int>,
                  First<int, Entry<int, int>>> PairHashtable;

TEST("require that hashtable can store pairs of <key, unique_ptr to value>") {
    PairHashtable table(100);
    table.insert(make_pair(42, std::unique_ptr<int>(new int(84))));
    PairHashtable::iterator it = table.find(42);
    EXPECT_EQUAL(84, *it->second);
    auto it2 = table.find(42);
    EXPECT_EQUAL(84, *it2->second);  // find is not destructive.

    std::unique_ptr<int> up = std::move(it->second);
    it2 = table.find(42);
    EXPECT_FALSE(it2->second.get());  // value has been moved out.
}

template<typename K> using set_hashtable =
    hashtable<K, K, vespalib::hash<K>, std::equal_to<K>, std::_Identity<K>>;

TEST("require that hashtable<int> can be copied") {
    set_hashtable<int> table(100);
    table.insert(42);
    set_hashtable<int> table2(table);
    EXPECT_EQUAL(42, *table2.find(42));
}

template<typename To, typename Vector>
struct FirstInVector : std::unary_function<To, Vector> {
    To &operator()(Vector& v) const { return v[0]; }
    const To& operator()(const Vector& v) const { return v[0]; }
};

TEST("require that hashtable<vector<int>> can be copied") {
    typedef hashtable<int, vector<int>, vespalib::hash<int>,
        std::equal_to<int>, FirstInVector<int, vector<int>>> VectorHashtable;
    VectorHashtable table(100);
    table.insert(std::vector<int>{2, 4, 6});
    VectorHashtable table2(table);
    EXPECT_EQUAL(6, (*table2.find(2))[2]);
    EXPECT_EQUAL(6, (*table.find(2))[2]);
}

}  // namespace

TEST_MAIN() { TEST_RUN_ALL(); }