1e735f23018b398f45bd052b63616d7a45e29515bJeff Brown/*
2e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * Copyright (C) 2011 The Android Open Source Project
3e735f23018b398f45bd052b63616d7a45e29515bJeff Brown *
4e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * you may not use this file except in compliance with the License.
6e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * You may obtain a copy of the License at
7e735f23018b398f45bd052b63616d7a45e29515bJeff Brown *
8e735f23018b398f45bd052b63616d7a45e29515bJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9e735f23018b398f45bd052b63616d7a45e29515bJeff Brown *
10e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * Unless required by applicable law or agreed to in writing, software
11e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * See the License for the specific language governing permissions and
14e735f23018b398f45bd052b63616d7a45e29515bJeff Brown * limitations under the License.
15e735f23018b398f45bd052b63616d7a45e29515bJeff Brown */
16e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
17e735f23018b398f45bd052b63616d7a45e29515bJeff Brown#define LOG_TAG "BasicHashtable_test"
18e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
19e735f23018b398f45bd052b63616d7a45e29515bJeff Brown#include <utils/BasicHashtable.h>
20e735f23018b398f45bd052b63616d7a45e29515bJeff Brown#include <cutils/log.h>
21e735f23018b398f45bd052b63616d7a45e29515bJeff Brown#include <gtest/gtest.h>
22e735f23018b398f45bd052b63616d7a45e29515bJeff Brown#include <unistd.h>
23e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
2427d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albertnamespace {
25e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
26e735f23018b398f45bd052b63616d7a45e29515bJeff Browntypedef int SimpleKey;
27e735f23018b398f45bd052b63616d7a45e29515bJeff Browntypedef int SimpleValue;
2827d166cb3aecc003b2ea576ec23695aff78de1a5Dan Alberttypedef android::key_value_pair_t<SimpleKey, SimpleValue> SimpleEntry;
2927d166cb3aecc003b2ea576ec23695aff78de1a5Dan Alberttypedef android::BasicHashtable<SimpleKey, SimpleEntry> SimpleHashtable;
30e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
31e735f23018b398f45bd052b63616d7a45e29515bJeff Brownstruct ComplexKey {
32e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    int k;
33e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
34e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    explicit ComplexKey(int k) : k(k) {
35e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        instanceCount += 1;
36e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
37e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
38e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexKey(const ComplexKey& other) : k(other.k) {
39e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        instanceCount += 1;
40e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
41e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
42e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ~ComplexKey() {
43e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        instanceCount -= 1;
44e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
45e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
46e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    bool operator ==(const ComplexKey& other) const {
47e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        return k == other.k;
48e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
49e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
50e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    bool operator !=(const ComplexKey& other) const {
51e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        return k != other.k;
52e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
53e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
54e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    static ssize_t instanceCount;
55e735f23018b398f45bd052b63616d7a45e29515bJeff Brown};
56e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
57e735f23018b398f45bd052b63616d7a45e29515bJeff Brownssize_t ComplexKey::instanceCount = 0;
58e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
59e735f23018b398f45bd052b63616d7a45e29515bJeff Brownstruct ComplexValue {
60e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    int v;
61e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
62e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    explicit ComplexValue(int v) : v(v) {
63e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        instanceCount += 1;
64e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
65e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
66e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexValue(const ComplexValue& other) : v(other.v) {
67e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        instanceCount += 1;
68e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
69e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
70e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ~ComplexValue() {
71e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        instanceCount -= 1;
72e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
73e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
74e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    static ssize_t instanceCount;
75e735f23018b398f45bd052b63616d7a45e29515bJeff Brown};
76e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
77e735f23018b398f45bd052b63616d7a45e29515bJeff Brownssize_t ComplexValue::instanceCount = 0;
78e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
7927d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert} // namespace
8027d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert
8127d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert
8227d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albertnamespace android {
8327d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert
84e735f23018b398f45bd052b63616d7a45e29515bJeff Browntypedef key_value_pair_t<ComplexKey, ComplexValue> ComplexEntry;
85e735f23018b398f45bd052b63616d7a45e29515bJeff Browntypedef BasicHashtable<ComplexKey, ComplexEntry> ComplexHashtable;
86e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
8727d166cb3aecc003b2ea576ec23695aff78de1a5Dan Alberttemplate<> inline hash_t hash_type(const ComplexKey& value) {
8827d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert    return hash_type(value.k);
8927d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert}
9027d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert
91e735f23018b398f45bd052b63616d7a45e29515bJeff Brownclass BasicHashtableTest : public testing::Test {
92e735f23018b398f45bd052b63616d7a45e29515bJeff Brownprotected:
93e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    virtual void SetUp() {
94e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ComplexKey::instanceCount = 0;
95e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ComplexValue::instanceCount = 0;
96e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
97e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
98e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    virtual void TearDown() {
99e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
100e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
101e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
102e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    void assertInstanceCount(ssize_t keys, ssize_t values) {
103e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        if (keys != ComplexKey::instanceCount || values != ComplexValue::instanceCount) {
104e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            FAIL() << "Expected " << keys << " keys and " << values << " values "
105e735f23018b398f45bd052b63616d7a45e29515bJeff Brown                    "but there were actually " << ComplexKey::instanceCount << " keys and "
106e735f23018b398f45bd052b63616d7a45e29515bJeff Brown                    << ComplexValue::instanceCount << " values";
107e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        }
108e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
109e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
110e735f23018b398f45bd052b63616d7a45e29515bJeff Brownpublic:
111e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    template <typename TKey, typename TEntry>
112e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    static void cookieAt(const BasicHashtable<TKey, TEntry>& h, size_t index,
113e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            bool* collision, bool* present, hash_t* hash) {
114e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        uint32_t cookie = h.cookieAt(index);
115e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        *collision = cookie & BasicHashtable<TKey, TEntry>::Bucket::COLLISION;
116e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        *present = cookie & BasicHashtable<TKey, TEntry>::Bucket::PRESENT;
117e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        *hash = cookie & BasicHashtable<TKey, TEntry>::Bucket::HASH_MASK;
118e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
119e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
120e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    template <typename TKey, typename TEntry>
121e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    static const void* getBuckets(const BasicHashtable<TKey, TEntry>& h) {
122e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        return h.mBuckets;
123e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
124e735f23018b398f45bd052b63616d7a45e29515bJeff Brown};
125e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
126e735f23018b398f45bd052b63616d7a45e29515bJeff Browntemplate <typename TKey, typename TValue>
127e735f23018b398f45bd052b63616d7a45e29515bJeff Brownstatic size_t add(BasicHashtable<TKey, key_value_pair_t<TKey, TValue> >& h,
128e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        const TKey& key, const TValue& value) {
129e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    return h.add(hash_type(key), key_value_pair_t<TKey, TValue>(key, value));
130e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
131e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
132e735f23018b398f45bd052b63616d7a45e29515bJeff Browntemplate <typename TKey, typename TValue>
133e735f23018b398f45bd052b63616d7a45e29515bJeff Brownstatic ssize_t find(BasicHashtable<TKey, key_value_pair_t<TKey, TValue> >& h,
134e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ssize_t index, const TKey& key) {
135e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    return h.find(index, hash_type(key), key);
136e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
137e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
138e735f23018b398f45bd052b63616d7a45e29515bJeff Browntemplate <typename TKey, typename TValue>
139e735f23018b398f45bd052b63616d7a45e29515bJeff Brownstatic bool remove(BasicHashtable<TKey, key_value_pair_t<TKey, TValue> >& h,
140e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        const TKey& key) {
141e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ssize_t index = find(h, -1, key);
142e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    if (index >= 0) {
143e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        h.removeAt(index);
144e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        return true;
145e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
146e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    return false;
147e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
148e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
149e735f23018b398f45bd052b63616d7a45e29515bJeff Browntemplate <typename TEntry>
150e735f23018b398f45bd052b63616d7a45e29515bJeff Brownstatic void getKeyValue(const TEntry& entry, int* key, int* value);
151e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
152e735f23018b398f45bd052b63616d7a45e29515bJeff Browntemplate <> void getKeyValue(const SimpleEntry& entry, int* key, int* value) {
153e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    *key = entry.key;
154e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    *value = entry.value;
155e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
156e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
157e735f23018b398f45bd052b63616d7a45e29515bJeff Browntemplate <> void getKeyValue(const ComplexEntry& entry, int* key, int* value) {
158e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    *key = entry.key.k;
159e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    *value = entry.value.v;
160e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
161e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
162e735f23018b398f45bd052b63616d7a45e29515bJeff Browntemplate <typename TKey, typename TValue>
163e735f23018b398f45bd052b63616d7a45e29515bJeff Brownstatic void dump(BasicHashtable<TKey, key_value_pair_t<TKey, TValue> >& h) {
164eb0953307ce75cec031aedbf21abff08e5a737e5Steve Block    ALOGD("hashtable %p, size=%u, capacity=%u, bucketCount=%u",
165e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            &h, h.size(), h.capacity(), h.bucketCount());
166e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    for (size_t i = 0; i < h.bucketCount(); i++) {
167e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        bool collision, present;
168e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        hash_t hash;
169e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        BasicHashtableTest::cookieAt(h, i, &collision, &present, &hash);
170e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        if (present) {
171e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            int key, value;
172e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            getKeyValue(h.entryAt(i), &key, &value);
173eb0953307ce75cec031aedbf21abff08e5a737e5Steve Block            ALOGD("  [%3u] = collision=%d, present=%d, hash=0x%08x, key=%3d, value=%3d, "
174e735f23018b398f45bd052b63616d7a45e29515bJeff Brown                    "hash_type(key)=0x%08x",
175e735f23018b398f45bd052b63616d7a45e29515bJeff Brown                    i, collision, present, hash, key, value, hash_type(key));
176e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        } else {
177eb0953307ce75cec031aedbf21abff08e5a737e5Steve Block            ALOGD("  [%3u] = collision=%d, present=%d",
178e735f23018b398f45bd052b63616d7a45e29515bJeff Brown                    i, collision, present);
179e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        }
180e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
181e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
182e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
183e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, DefaultConstructor_WithDefaultProperties) {
184e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
185e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
186e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
187e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(3U, h.capacity());
188e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(5U, h.bucketCount());
189e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0.75f, h.loadFactor());
190e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
191e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
192e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Constructor_WithNonUnityLoadFactor) {
193e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h(52, 0.8f);
194e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
195e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
196e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(77U, h.capacity());
197e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(97U, h.bucketCount());
198e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0.8f, h.loadFactor());
199e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
200e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
201e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Constructor_WithUnityLoadFactorAndExactCapacity) {
202e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h(46, 1.0f);
203e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
204e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
205e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(46U, h.capacity()); // must be one less than bucketCount because loadFactor == 1.0f
206e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(47U, h.bucketCount());
207e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(1.0f, h.loadFactor());
208e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
209e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
210e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Constructor_WithUnityLoadFactorAndInexactCapacity) {
211e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h(42, 1.0f);
212e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
213e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
214e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(46U, h.capacity()); // must be one less than bucketCount because loadFactor == 1.0f
215e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(47U, h.bucketCount());
216e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(1.0f, h.loadFactor());
217e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
218e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
219e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, FindAddFindRemoveFind_OneEntry) {
220e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
221e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ssize_t index = find(h, -1, 8);
222e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(-1, index);
223e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
224e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    index = add(h, 8, 1);
225e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(1U, h.size());
226e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
227e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(index, find(h, -1, 8));
228e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(8, h.entryAt(index).key);
229e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(1, h.entryAt(index).value);
230e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
231e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    index = find(h, index, 8);
232e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(-1, index);
233e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
234e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_TRUE(remove(h, 8));
235e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(0U, h.size());
236e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
237e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    index = find(h, -1, 8);
238e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(-1, index);
239e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
240e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
241e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, FindAddFindRemoveFind_MultipleEntryWithUniqueKey) {
242e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    const size_t N = 11;
243e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
244e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
245e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    for (size_t i = 0; i < N; i++) {
246e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ssize_t index = find(h, -1, int(i));
247e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(-1, index);
248e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
249e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        index = add(h, int(i), int(i * 10));
250e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(i + 1, h.size());
251e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
252e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(index, find(h, -1, int(i)));
253e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(int(i), h.entryAt(index).key);
254e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(int(i * 10), h.entryAt(index).value);
255e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
256e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        index = find(h, index, int(i));
257e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(-1, index);
258e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
259e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
260e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    for (size_t i = N; --i > 0; ) {
261e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_TRUE(remove(h, int(i))) << "i = " << i;
262e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(i, h.size());
263e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
264e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ssize_t index = find(h, -1, int(i));
265e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(-1, index);
266e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
267e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
268e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
269e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, FindAddFindRemoveFind_MultipleEntryWithDuplicateKey) {
270e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    const size_t N = 11;
271e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    const int K = 1;
272e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
273e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
274e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    for (size_t i = 0; i < N; i++) {
275e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ssize_t index = find(h, -1, K);
276e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        if (i == 0) {
277e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            ASSERT_EQ(-1, index);
278e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        } else {
279e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            ASSERT_NE(-1, index);
280e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        }
281e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
282e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        add(h, K, int(i));
283e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(i + 1, h.size());
284e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
285e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        index = -1;
286e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        int values = 0;
287e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        for (size_t j = 0; j <= i; j++) {
288e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            index = find(h, index, K);
289e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            ASSERT_GE(index, 0);
290e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            ASSERT_EQ(K, h.entryAt(index).key);
291e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            values |= 1 << h.entryAt(index).value;
292e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        }
293e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(values, (1 << (i + 1)) - 1);
294e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
295e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        index = find(h, index, K);
296e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(-1, index);
297e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
298e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
299e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    for (size_t i = N; --i > 0; ) {
300e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_TRUE(remove(h, K)) << "i = " << i;
301e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(i, h.size());
302e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
303e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ssize_t index = -1;
304e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        for (size_t j = 0; j < i; j++) {
305e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            index = find(h, index, K);
306e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            ASSERT_GE(index, 0);
307e735f23018b398f45bd052b63616d7a45e29515bJeff Brown            ASSERT_EQ(K, h.entryAt(index).key);
308e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        }
309e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
310e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        index = find(h, index, K);
311e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(-1, index);
312e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
313e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
314e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
315e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Clear_WhenAlreadyEmpty_DoesNothing) {
316e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
317e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h.clear();
318e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
319e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
320e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(3U, h.capacity());
321e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(5U, h.bucketCount());
322e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0.75f, h.loadFactor());
323e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
324e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
325e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Clear_AfterElementsAdded_RemovesThem) {
326e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
327e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, 0, 0);
328e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, 1, 0);
329e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h.clear();
330e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
331e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
332e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(3U, h.capacity());
333e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(5U, h.bucketCount());
334e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0.75f, h.loadFactor());
335e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
336e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
337e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Clear_AfterElementsAdded_DestroysThem) {
338e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h;
339e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, ComplexKey(0), ComplexValue(0));
340e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, ComplexKey(1), ComplexValue(0));
341e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
342e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
343e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h.clear();
344e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
345e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
346e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
347e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(3U, h.capacity());
348e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(5U, h.bucketCount());
349e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0.75f, h.loadFactor());
350e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
351e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
352e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Remove_AfterElementsAdded_DestroysThem) {
353e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h;
354e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, ComplexKey(0), ComplexValue(0));
355e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, ComplexKey(1), ComplexValue(0));
356e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
357e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
358e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_TRUE(remove(h, ComplexKey(0)));
359e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(1, 1));
360e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
361e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_TRUE(remove(h, ComplexKey(1)));
362e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
363e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
364e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
365e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(3U, h.capacity());
366e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(5U, h.bucketCount());
367e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0.75f, h.loadFactor());
368e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
369e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
370e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Destructor_AfterElementsAdded_DestroysThem) {
371e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    {
372e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ComplexHashtable h;
373e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        add(h, ComplexKey(0), ComplexValue(0));
374e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        add(h, ComplexKey(1), ComplexValue(0));
375e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
376e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    } // h is destroyed here
377e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
378e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
379e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
380e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
381e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Next_WhenEmpty_ReturnsMinusOne) {
382e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
383e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
384e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(-1, h.next(-1));
385e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
386e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
387e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Next_WhenNonEmpty_IteratesOverAllEntries) {
388e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    const int N = 88;
389e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
390e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
391e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    for (int i = 0; i < N; i++) {
392e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        add(h, i, i * 10);
393e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
394e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
395e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    bool set[N];
396e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    memset(set, 0, sizeof(bool) * N);
397e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    int count = 0;
398e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    for (ssize_t index = -1; (index = h.next(index)) != -1; ) {
399e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_GE(index, 0);
400e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_LT(size_t(index), h.bucketCount());
401e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
402e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        const SimpleEntry& entry = h.entryAt(index);
403e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_GE(entry.key, 0);
404e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_LT(entry.key, N);
405cdc1cfb3e51f3caddc1f290b46dc789c036f22edSasha Levitskiy        ASSERT_FALSE(set[entry.key]);
406e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        ASSERT_EQ(entry.key * 10, entry.value);
407e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
408e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        set[entry.key] = true;
409e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        count += 1;
410e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
411e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(N, count);
412e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
413e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
414e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Add_RehashesOnDemand) {
415e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    SimpleHashtable h;
416e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    size_t initialCapacity = h.capacity();
417e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    size_t initialBucketCount = h.bucketCount();
418e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
419e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    for (size_t i = 0; i < initialCapacity; i++) {
420e735f23018b398f45bd052b63616d7a45e29515bJeff Brown        add(h, int(i), 0);
421e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    }
422e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
423e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(initialCapacity, h.size());
424e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(initialCapacity, h.capacity());
425e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(initialBucketCount, h.bucketCount());
426e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
427e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, -1, -1);
428e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
429e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(initialCapacity + 1, h.size());
430e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_GT(h.capacity(), initialCapacity);
431e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_GT(h.bucketCount(), initialBucketCount);
432e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_GT(h.bucketCount(), h.capacity());
433e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
434e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
435e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Rehash_WhenCapacityAndBucketCountUnchanged_DoesNothing) {
436e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h;
437e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, ComplexKey(0), ComplexValue(0));
438e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    const void* oldBuckets = getBuckets(h);
439e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NE((void*)NULL, oldBuckets);
440e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(1, 1));
441e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
442e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h.rehash(h.capacity(), h.loadFactor());
443e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
444e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(oldBuckets, getBuckets(h));
445e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(1, 1));
446e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
447e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
448e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Rehash_WhenEmptyAndHasNoBuckets_ButDoesNotAllocateBuckets) {
449e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h;
450e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ((void*)NULL, getBuckets(h));
451e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
452e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
453e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h.rehash(9, 1.0f);
454e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
455e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
456e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(10U, h.capacity());
457e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(11U, h.bucketCount());
458e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(1.0f, h.loadFactor());
459e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ((void*)NULL, getBuckets(h));
460e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
461e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
462e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
463e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Rehash_WhenEmptyAndHasBuckets_ReleasesBucketsAndSetsCapacity) {
464e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h(10);
465e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, ComplexKey(0), ComplexValue(0));
466e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_TRUE(remove(h, ComplexKey(0)));
467e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NE((void*)NULL, getBuckets(h));
468e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
469e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
470e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h.rehash(0, 0.75f);
471e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
472e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h.size());
473e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(3U, h.capacity());
474e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(5U, h.bucketCount());
475e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0.75f, h.loadFactor());
476e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ((void*)NULL, getBuckets(h));
477e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
478e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
479e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
480e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, Rehash_WhenLessThanCurrentCapacity_ShrinksBuckets) {
481e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h(10);
482e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, ComplexKey(0), ComplexValue(0));
483e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h, ComplexKey(1), ComplexValue(1));
484e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    const void* oldBuckets = getBuckets(h);
485e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
486e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
487e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h.rehash(0, 0.75f);
488e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
489e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(2U, h.size());
490e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(3U, h.capacity());
491e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(5U, h.bucketCount());
492e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0.75f, h.loadFactor());
493e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_NE(oldBuckets, getBuckets(h));
494e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
495e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
496e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
497e735f23018b398f45bd052b63616d7a45e29515bJeff BrownTEST_F(BasicHashtableTest, CopyOnWrite) {
498e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h1;
499e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h1, ComplexKey(0), ComplexValue(0));
500e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h1, ComplexKey(1), ComplexValue(1));
501e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    const void* originalBuckets = getBuckets(h1);
502e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
503e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ssize_t index0 = find(h1, -1, ComplexKey(0));
504e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_GE(index0, 0);
505e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
506e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    // copy constructor acquires shared reference
507e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h2(h1);
508e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
509e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(originalBuckets, getBuckets(h2));
510e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h1.size(), h2.size());
511e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h1.capacity(), h2.capacity());
512e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h1.bucketCount(), h2.bucketCount());
513e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h1.loadFactor(), h2.loadFactor());
514e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(index0, find(h2, -1, ComplexKey(0)));
515e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
516e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    // operator= acquires shared reference
517e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ComplexHashtable h3;
518e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h3 = h2;
519e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
520e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(originalBuckets, getBuckets(h3));
521e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h1.size(), h3.size());
522e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h1.capacity(), h3.capacity());
523e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h1.bucketCount(), h3.bucketCount());
524e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h1.loadFactor(), h3.loadFactor());
525e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(index0, find(h3, -1, ComplexKey(0)));
526e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
527e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    // editEntryAt copies shared contents
528e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h1.editEntryAt(index0).value.v = 42;
529e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(4, 4));
530e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NE(originalBuckets, getBuckets(h1));
531e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(42, h1.entryAt(index0).value.v);
532e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0, h2.entryAt(index0).value.v);
533e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0, h3.entryAt(index0).value.v);
534e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
535e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    // clear releases reference to shared contents
536e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h2.clear();
537e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(4, 4));
538e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h2.size());
539e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NE(originalBuckets, getBuckets(h2));
540e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
541e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    // operator= acquires shared reference, destroys unshared contents
542e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h1 = h3;
543e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
544e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(originalBuckets, getBuckets(h1));
545e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h3.size(), h1.size());
546e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h3.capacity(), h1.capacity());
547e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h3.bucketCount(), h1.bucketCount());
548e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(h3.loadFactor(), h1.loadFactor());
549e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(index0, find(h1, -1, ComplexKey(0)));
550e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
551e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    // add copies shared contents
552e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    add(h1, ComplexKey(2), ComplexValue(2));
553e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(5, 5));
554e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NE(originalBuckets, getBuckets(h1));
555e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(3U, h1.size());
556e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h2.size());
557e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(2U, h3.size());
558e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
559e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    // remove copies shared contents
560e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h1 = h3;
561e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
562e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(originalBuckets, getBuckets(h1));
563e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h1.removeAt(index0);
564e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(3, 3));
565e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NE(originalBuckets, getBuckets(h1));
566e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(1U, h1.size());
567e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h2.size());
568e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(2U, h3.size());
569e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
570e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    // rehash copies shared contents
571e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h1 = h3;
572e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
573e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_EQ(originalBuckets, getBuckets(h1));
574e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    h1.rehash(10, 1.0f);
575e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(4, 4));
576e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    ASSERT_NE(originalBuckets, getBuckets(h1));
577e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(2U, h1.size());
578e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(0U, h2.size());
579e735f23018b398f45bd052b63616d7a45e29515bJeff Brown    EXPECT_EQ(2U, h3.size());
580e735f23018b398f45bd052b63616d7a45e29515bJeff Brown}
581e735f23018b398f45bd052b63616d7a45e29515bJeff Brown
582e735f23018b398f45bd052b63616d7a45e29515bJeff Brown} // namespace android
583