| Index: runtime/bin/hashmap_test.cc
|
| diff --git a/runtime/bin/hashmap_test.cc b/runtime/bin/hashmap_test.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..409fde24b0f0b8d9111bf76899967b1793843869
|
| --- /dev/null
|
| +++ b/runtime/bin/hashmap_test.cc
|
| @@ -0,0 +1,169 @@
|
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +#include "bin/hashmap.h"
|
| +#include "platform/assert.h"
|
| +#include "platform/globals.h"
|
| +#include "vm/unit_test.h"
|
| +
|
| +// Default initial size of hashmaps used in these tests.
|
| +static intptr_t kInitialSize = 8;
|
| +
|
| +
|
| +typedef uint32_t (*IntKeyHash)(uint32_t key);
|
| +
|
| +
|
| +class IntSet {
|
| + public:
|
| + explicit IntSet(IntKeyHash hash)
|
| + : hash_(hash), map_(HashMap::SamePointerValue, kInitialSize) {}
|
| +
|
| + void Insert(int x) {
|
| + EXPECT_NE(0, x); // 0 corresponds to (void*)NULL - illegal key value
|
| + HashMap::Entry* p = map_.Lookup(reinterpret_cast<void*>(x), hash_(x), true);
|
| + EXPECT(p != NULL); // insert is set!
|
| + EXPECT_EQ(reinterpret_cast<void*>(x), p->key);
|
| + // We don't care about p->value.
|
| + }
|
| +
|
| + void Remove(int x) {
|
| + EXPECT_NE(0, x); // 0 corresponds to (void*)NULL - illegal key value
|
| + map_.Remove(reinterpret_cast<void*>(x), hash_(x));
|
| + }
|
| +
|
| + bool Present(int x) {
|
| + HashMap::Entry* p =
|
| + map_.Lookup(reinterpret_cast<void*>(x), hash_(x), false);
|
| + if (p != NULL) {
|
| + EXPECT_EQ(reinterpret_cast<void*>(x), p->key);
|
| + }
|
| + return p != NULL;
|
| + }
|
| +
|
| + void Clear() {
|
| + map_.Clear();
|
| + }
|
| +
|
| + uint32_t occupancy() const {
|
| + uint32_t count = 0;
|
| + for (HashMap::Entry* p = map_.Start(); p != NULL; p = map_.Next(p)) {
|
| + count++;
|
| + }
|
| + EXPECT_EQ(map_.occupancy_, count);
|
| + return count;
|
| + }
|
| +
|
| + private:
|
| + IntKeyHash hash_;
|
| + HashMap map_;
|
| +};
|
| +
|
| +
|
| +static uint32_t WordHash(uint32_t key) { return dart::Utils::WordHash(key); }
|
| +static uint32_t Hash(uint32_t key) { return 23; }
|
| +static uint32_t CollisionHash1(uint32_t key) { return key & 0x3; }
|
| +static uint32_t CollisionHash2(uint32_t key) { return kInitialSize - 1; }
|
| +static uint32_t CollisionHash3(uint32_t key) { return kInitialSize - 2; }
|
| +static uint32_t CollisionHash4(uint32_t key) { return kInitialSize - 2; }
|
| +
|
| +
|
| +void TestSet(IntKeyHash hash, int size) {
|
| + IntSet set(hash);
|
| + EXPECT_EQ(0u, set.occupancy());
|
| +
|
| + set.Insert(1);
|
| + set.Insert(2);
|
| + set.Insert(3);
|
| + set.Insert(4);
|
| + EXPECT_EQ(4u, set.occupancy());
|
| +
|
| + set.Insert(2);
|
| + set.Insert(3);
|
| + EXPECT_EQ(4u, set.occupancy());
|
| +
|
| + EXPECT(set.Present(1));
|
| + EXPECT(set.Present(2));
|
| + EXPECT(set.Present(3));
|
| + EXPECT(set.Present(4));
|
| + EXPECT(!set.Present(5));
|
| + EXPECT_EQ(4u, set.occupancy());
|
| +
|
| + set.Remove(1);
|
| + EXPECT(!set.Present(1));
|
| + EXPECT(set.Present(2));
|
| + EXPECT(set.Present(3));
|
| + EXPECT(set.Present(4));
|
| + EXPECT_EQ(3u, set.occupancy());
|
| +
|
| + set.Remove(3);
|
| + EXPECT(!set.Present(1));
|
| + EXPECT(set.Present(2));
|
| + EXPECT(!set.Present(3));
|
| + EXPECT(set.Present(4));
|
| + EXPECT_EQ(2u, set.occupancy());
|
| +
|
| + set.Remove(4);
|
| + EXPECT(!set.Present(1));
|
| + EXPECT(set.Present(2));
|
| + EXPECT(!set.Present(3));
|
| + EXPECT(!set.Present(4));
|
| + EXPECT_EQ(1u, set.occupancy());
|
| +
|
| + set.Clear();
|
| + EXPECT_EQ(0u, set.occupancy());
|
| +
|
| + // Insert a long series of values.
|
| + const int start = 453;
|
| + const int factor = 13;
|
| + const int offset = 7;
|
| + const uint32_t n = size;
|
| +
|
| + int x = start;
|
| + for (uint32_t i = 0; i < n; i++) {
|
| + EXPECT_EQ(i, set.occupancy());
|
| + set.Insert(x);
|
| + x = x * factor + offset;
|
| + }
|
| + EXPECT_EQ(n, set.occupancy());
|
| +
|
| + // Verify the same sequence of values.
|
| + x = start;
|
| + for (uint32_t i = 0; i < n; i++) {
|
| + EXPECT(set.Present(x));
|
| + x = x * factor + offset;
|
| + }
|
| + EXPECT_EQ(n, set.occupancy());
|
| +
|
| + // Remove all these values.
|
| + x = start;
|
| + for (uint32_t i = 0; i < n; i++) {
|
| + EXPECT_EQ(n - i, set.occupancy());
|
| + EXPECT(set.Present(x));
|
| + set.Remove(x);
|
| + EXPECT(!set.Present(x));
|
| + x = x * factor + offset;
|
| +
|
| + // Verify the the expected values are still there.
|
| + int y = start;
|
| + for (uint32_t j = 0; j < n; j++) {
|
| + if (j <= i) {
|
| + EXPECT(!set.Present(y));
|
| + } else {
|
| + EXPECT(set.Present(y));
|
| + }
|
| + y = y * factor + offset;
|
| + }
|
| + }
|
| + EXPECT_EQ(0u, set.occupancy());
|
| +}
|
| +
|
| +
|
| +UNIT_TEST_CASE(Set) {
|
| + TestSet(WordHash, 100);
|
| + TestSet(Hash, 100);
|
| + TestSet(CollisionHash1, 50);
|
| + TestSet(CollisionHash2, 50);
|
| + TestSet(CollisionHash3, 50);
|
| + TestSet(CollisionHash4, 50);
|
| +}
|
|
|