mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
2707880f1b
Bug: https://github.com/dart-lang/sdk/issues/39427 Change-Id: I74e0eee623d88005fb2893d03e284a87daa09260 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/146696 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
179 lines
4.2 KiB
C++
179 lines
4.2 KiB
C++
// 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 "platform/hashmap.h"
|
|
#include "platform/assert.h"
|
|
#include "platform/globals.h"
|
|
#include "vm/unit_test.h"
|
|
|
|
namespace dart {
|
|
|
|
// 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_(SimpleHashMap::SamePointerValue, kInitialSize) {}
|
|
|
|
void Insert(int x) {
|
|
EXPECT_NE(0, x); // 0 corresponds to (void*)NULL - illegal key value
|
|
SimpleHashMap::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) {
|
|
SimpleHashMap::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 (SimpleHashMap::Entry* p = map_.Start(); p != NULL; p = map_.Next(p)) {
|
|
count++;
|
|
}
|
|
EXPECT_EQ(map_.occupancy_, count);
|
|
return count;
|
|
}
|
|
|
|
private:
|
|
IntKeyHash hash_;
|
|
SimpleHashMap 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 uint32_t start = 453;
|
|
const uint32_t factor = 13;
|
|
const uint32_t offset = 7;
|
|
const uint32_t n = size;
|
|
|
|
uint32_t 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 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());
|
|
}
|
|
|
|
VM_UNIT_TEST_CASE(SimpleHashMap_Basic) {
|
|
TestSet(WordHash, 100);
|
|
TestSet(Hash, 100);
|
|
TestSet(CollisionHash1, 50);
|
|
TestSet(CollisionHash2, 50);
|
|
TestSet(CollisionHash3, 50);
|
|
TestSet(CollisionHash4, 50);
|
|
}
|
|
|
|
} // namespace dart
|