207 lines
7.6 KiB
Python
207 lines
7.6 KiB
Python
from stdint import *
|
|
import w32.win32console
|
|
import t, c
|
|
from t import CInt, CExport
|
|
import stdio
|
|
import stdlib
|
|
import string
|
|
import memhub
|
|
import hashtable
|
|
import testcheck
|
|
|
|
|
|
def main() -> CInt | CExport:
|
|
w32.win32console.SetConsoleCP(65001)
|
|
w32.win32console.SetConsoleOutputCP(65001)
|
|
|
|
testcheck.begin("HashTableTest: 开放寻址哈希表测试")
|
|
|
|
# 分配内存竞技场
|
|
arena: bytes = stdlib.malloc(65536)
|
|
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
|
|
|
|
# === Test 1: 基本插入和查找 ===
|
|
testcheck.section("Test 1: 基本插入和查找 (set_int)")
|
|
ht: hashtable.HashTable = hashtable.HashTable(bd)
|
|
ht.set_int("alpha", 10)
|
|
ht.set_int("beta", 20)
|
|
ht.set_int("gamma", 30)
|
|
n: t.CSizeT = len(ht)
|
|
stdio.printf("len=%lu\n", n)
|
|
testcheck.check(n == 3, "ht len OK (3)", "ht len FAILED")
|
|
|
|
p1: t.CPtr = ht["alpha"]
|
|
v1: int = c.Deref(p1)
|
|
p2: t.CPtr = ht["beta"]
|
|
v2: int = c.Deref(p2)
|
|
p3: t.CPtr = ht["gamma"]
|
|
v3: int = c.Deref(p3)
|
|
stdio.printf("alpha=%d beta=%d gamma=%d\n", v1, v2, v3)
|
|
testcheck.check(v1 == 10, "ht[alpha]==10 OK", "ht[alpha] FAILED")
|
|
testcheck.check(v2 == 20, "ht[beta]==20 OK", "ht[beta] FAILED")
|
|
testcheck.check(v3 == 30, "ht[gamma]==30 OK", "ht[gamma] FAILED")
|
|
|
|
# === Test 2: 更新已有键 ===
|
|
testcheck.section("Test 2: 更新已有键")
|
|
ht.set_int("beta", 99)
|
|
p2b: t.CPtr = ht["beta"]
|
|
v2b: int = c.Deref(p2b)
|
|
stdio.printf("beta(updated)=%d\n", v2b)
|
|
testcheck.check(v2b == 99, "ht update OK", "ht update FAILED")
|
|
testcheck.check(len(ht) == 3, "ht len still 3 OK", "ht len changed FAILED")
|
|
|
|
# === Test 3: get with default ===
|
|
testcheck.section("Test 3: get with default")
|
|
gv: t.CPtr = ht.get("missing", None)
|
|
testcheck.check(gv == None, "ht get missing OK (None)", "ht get missing FAILED")
|
|
gp: t.CPtr = ht.get("alpha", None)
|
|
ga: int = c.Deref(gp)
|
|
stdio.printf("get(alpha)=%d\n", ga)
|
|
testcheck.check(ga == 10, "ht get existing OK", "ht get existing FAILED")
|
|
|
|
# === Test 4: contains ===
|
|
testcheck.section("Test 4: contains (in)")
|
|
has_alpha: t.CInt = "alpha" in ht
|
|
has_missing: t.CInt = "missing" in ht
|
|
stdio.printf("contains(alpha)=%d contains(missing)=%d\n", has_alpha, has_missing)
|
|
testcheck.check(has_alpha == 1, "contains alpha OK", "contains alpha FAILED")
|
|
testcheck.check(has_missing == 0, "not contains missing OK", "contains missing FAILED")
|
|
|
|
# === Test 5: 删除 ===
|
|
testcheck.section("Test 5: 删除 (del)")
|
|
deleted: t.CInt = ht.__delitem__("beta")
|
|
stdio.printf("del beta=%d\n", deleted)
|
|
testcheck.check(deleted == 1, "del beta OK", "del beta FAILED")
|
|
testcheck.check(len(ht) == 2, "ht len 2 after del OK", "ht len after del FAILED")
|
|
has_beta: t.CInt = "beta" in ht
|
|
testcheck.check(has_beta == 0, "beta gone OK", "beta still exists FAILED")
|
|
|
|
# 删除不存在的 key
|
|
del_missing: t.CInt = ht.__delitem__("nokey")
|
|
testcheck.check(del_missing == 0, "del missing returns 0 OK", "del missing FAILED")
|
|
|
|
# === Test 6: 删除后重新插入 ===
|
|
testcheck.section("Test 6: 删除后重新插入")
|
|
ht.set_int("beta", 555)
|
|
p2c: t.CPtr = ht["beta"]
|
|
v2c: int = c.Deref(p2c)
|
|
stdio.printf("beta(re-inserted)=%d\n", v2c)
|
|
testcheck.check(v2c == 555, "ht re-insert beta OK", "ht re-insert beta FAILED")
|
|
testcheck.check(len(ht) == 3, "ht len 3 after re-insert OK", "ht len after re-insert FAILED")
|
|
|
|
# === Test 7: 迭代器 ===
|
|
testcheck.section("Test 7: 迭代器 for key in ht")
|
|
iter_count: int = 0
|
|
for key in ht:
|
|
kp: t.CPtr = ht[key]
|
|
val: int = c.Deref(kp)
|
|
stdio.printf("ht[%s]=%d\n", key, val)
|
|
iter_count += 1
|
|
testcheck.check(iter_count == 3, "ht iter OK (3)", "ht iter FAILED")
|
|
|
|
# === Test 8: 字符串值 ===
|
|
testcheck.section("Test 8: 字符串值 (set_str)")
|
|
ht2: hashtable.HashTable = hashtable.HashTable(bd)
|
|
ht2.set_str("name", "Alice")
|
|
ht2.set_str("city", "Beijing")
|
|
ht2.set_str("lang", "TransPyC")
|
|
n2: t.CSizeT = len(ht2)
|
|
stdio.printf("ht2 len=%lu\n", n2)
|
|
testcheck.check(n2 == 3, "ht set_str len OK (3)", "ht set_str len FAILED")
|
|
|
|
name_p: t.CPtr = ht2["name"]
|
|
city_p: t.CPtr = ht2["city"]
|
|
lang_p: t.CPtr = ht2["lang"]
|
|
name: str = name_p
|
|
city: str = city_p
|
|
lang: str = lang_p
|
|
stdio.printf("name=%s city=%s lang=%s\n", name, city, lang)
|
|
testcheck.check(name == "Alice", "ht str name OK", "ht str name FAILED")
|
|
testcheck.check(city == "Beijing", "ht str city OK", "ht str city FAILED")
|
|
testcheck.check(lang == "TransPyC", "ht str lang OK", "ht str lang FAILED")
|
|
|
|
# === Test 9: 扩容测试 ===
|
|
testcheck.section("Test 9: 扩容测试 (>16 个元素)")
|
|
ht3: hashtable.HashTable = hashtable.HashTable(bd)
|
|
i: int = 0
|
|
while i < 50:
|
|
key_buf: str = stdlib.malloc(16)
|
|
stdio.sprintf(key_buf, "key%d", i)
|
|
ht3.set_int(key_buf, i * 100)
|
|
i += 1
|
|
n3: t.CSizeT = len(ht3)
|
|
stdio.printf("ht3 len=%lu (after 50 inserts)\n", n3)
|
|
testcheck.check(n3 == 50, "ht expand OK (50)", "ht expand FAILED")
|
|
|
|
# 验证几个值
|
|
k5: str = stdlib.malloc(16)
|
|
stdio.sprintf(k5, "key5")
|
|
p5: t.CPtr = ht3[k5]
|
|
v5: int = c.Deref(p5)
|
|
stdio.printf("ht3[key5]=%d\n", v5)
|
|
testcheck.check(v5 == 500, "ht expand key5 OK", "ht expand key5 FAILED")
|
|
|
|
k25: str = stdlib.malloc(16)
|
|
stdio.sprintf(k25, "key25")
|
|
p25: t.CPtr = ht3[k25]
|
|
v25: int = c.Deref(p25)
|
|
stdio.printf("ht3[key25]=%d\n", v25)
|
|
testcheck.check(v25 == 2500, "ht expand key25 OK", "ht expand key25 FAILED")
|
|
|
|
k49: str = stdlib.malloc(16)
|
|
stdio.sprintf(k49, "key49")
|
|
p49: t.CPtr = ht3[k49]
|
|
v49: int = c.Deref(p49)
|
|
stdio.printf("ht3[key49]=%d\n", v49)
|
|
testcheck.check(v49 == 4900, "ht expand key49 OK", "ht expand key49 FAILED")
|
|
|
|
# === Test 10: 扩容后迭代 ===
|
|
testcheck.section("Test 10: 扩容后迭代")
|
|
iter_count3: int = 0
|
|
for k in ht3:
|
|
iter_count3 += 1
|
|
stdio.printf("ht3 iter count=%d\n", iter_count3)
|
|
testcheck.check(iter_count3 == 50, "ht expand iter OK (50)", "ht expand iter FAILED")
|
|
|
|
# === Test 11: 删除后扩容 ===
|
|
testcheck.section("Test 11: 批量删除后操作")
|
|
j: int = 0
|
|
while j < 25:
|
|
del_buf: str = stdlib.malloc(16)
|
|
stdio.sprintf(del_buf, "key%d", j)
|
|
del ht3[del_buf]
|
|
j += 1
|
|
n3b: t.CSizeT = len(ht3)
|
|
stdio.printf("ht3 len=%lu (after 25 deletes)\n", n3b)
|
|
testcheck.check(n3b == 25, "ht after del OK (25)", "ht after del FAILED")
|
|
|
|
# 验证剩余的值
|
|
k30: str = stdlib.malloc(16)
|
|
stdio.sprintf(k30, "key30")
|
|
p30: t.CPtr = ht3[k30]
|
|
v30: int = c.Deref(p30)
|
|
stdio.printf("ht3[key30]=%d\n", v30)
|
|
testcheck.check(v30 == 3000, "ht key30 after del OK", "ht key30 after del FAILED")
|
|
|
|
# 验证已删除的 key 不存在
|
|
k0: str = stdlib.malloc(16)
|
|
stdio.sprintf(k0, "key0")
|
|
has_k0: t.CInt = k0 in ht3
|
|
testcheck.check(has_k0 == 0, "ht key0 deleted OK", "ht key0 still exists FAILED")
|
|
|
|
# === Test 12: 空表操作 ===
|
|
testcheck.section("Test 12: 空表操作")
|
|
ht4: hashtable.HashTable = hashtable.HashTable(bd)
|
|
testcheck.check(len(ht4) == 0, "empty ht len 0 OK", "empty ht len FAILED")
|
|
empty_get: t.CPtr = ht4.get("none", None)
|
|
testcheck.check(empty_get == None, "empty ht get OK", "empty ht get FAILED")
|
|
has_none: t.CInt = "none" in ht4
|
|
testcheck.check(has_none == 0, "empty ht contains OK", "empty ht contains FAILED")
|
|
empty_iter: int = 0
|
|
for ek in ht4:
|
|
empty_iter += 1
|
|
testcheck.check(empty_iter == 0, "empty ht iter OK (0)", "empty ht iter FAILED")
|
|
|
|
stdlib.free(arena)
|
|
return testcheck.end()
|