summaryrefslogtreecommitdiff
path: root/htab/+test.ha
blob: 518e97d9bb484bc08f0c9f1a61de4ab99117b25b (plain)
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
use fmt;
use hash;
use hash::fnv;
use math::random;

fn test_eq(ctx: *opaque, entry: *opaque) bool =
	*(ctx: *u64) == *(entry: *u64);

fn test_fnvhash(x: u64) u64 = {
	let h = fnv::fnv64a();
	hash::write(&h, &x: *[8]u8);
	return fnv::sum64(&h);
};

fn test_garbagehash(x: u64) u64 =
	0x0123456789abcdef;

fn test_table(sz: size, hash_fn: *fn(x: u64) u64, rng: *random::random) void = {
	fmt::printf("{} ", sz)!;
	static let array: [1024]bool = [false...];
	for (let i = 0z; i < len(array); i += 1) {
		array[i] = false;
	};
	let tab = new(0, sz);
	defer finish(&tab);

	for (let i = 0; i < 100000; i += 1) {
		const x = random::u64n(rng, len(array): u64);
		const hash = hash_fn(x);
		match (get(&tab, hash, &test_eq, &x, sz)) {
		case let entry: *opaque =>
			assert(array[x: size]);
			assert(*(entry: *u64) == x);
			del(&tab, entry, sz);
			array[x: size] = false;
		case null =>
			assert(!array[x: size]);
			const entry = add(&tab, hash, sz);
			array[x: size] = true;
			*(entry: *u64) = x;
		};
	};

	for (let x = 0u64; x < len(array): u64; x += 1) {
		const hash = hash_fn(x);
		get(&tab, hash, &test_eq, &x, sz);
	};

	fmt::println()!;
};

@test fn table() void = {
	let rng = random::init(42);

	fmt::println("fnvhash:")!;
	for (let i = 8z; i < 128; i += 8)
		test_table(i, &test_fnvhash, &rng);
	fmt::println("garbagehash:")!;
	for (let i = 8z; i < 128; i += 8)
		test_table(i, &test_garbagehash, &rng);
};