Files
Viper_RegressionTesting/NoVTableTest/App/main.vp
T
TermiNexus ee6461be46 chore(comments): Test 仓注释英文化(R11)
把 81 个 .vp 文件的中文 # 注释与三引号文档串改写为简洁英文,每个连续注释块 <=2 行;运行时中文字符串字面量(testcheck.begin/print 等用户可见消息)保持原样。骨架比对 HEAD 与工作区 112 文件漂移 0,全量 77/77 顺序回归通过。
2026-10-05 22:43:38 +08:00

470 lines
14 KiB
Plaintext

import t
import stdio
import string
import testcheck
import linkedlist
import viperlib
import stdlib
# Subclass of linkedlist.LinkedNode: flattened fields, no vtable; OOP wrappers are auto-generated.
# Cast LinkedNode* back to Node* explicitly: (Node | t.CPtr)(ptr)
class Node(linkedlist.LinkedNode):
value: int
# --- Test 1: append + child_count ---
def test_append():
testcheck.section("Test 1: append")
root: Node = Node()
a: Node = Node()
b: Node = Node()
c: Node = Node()
a.value = 10
b.value = 20
c.value = 30
root.append(a)
root.append(b)
root.append(c)
testcheck.check(root.child_count == 3,
"append count=3",
"append count fail")
# verify order (explicit downcast LinkedNode* -> Node*)
c1: Node* = (Node*)(root.child)
c2: Node* = (Node*)(c1.next)
c3: Node* = (Node*)(c2.next)
testcheck.check(c1.value == 10 and c2.value == 20 and c3.value == 30,
"order 10,20,30",
"order fail")
# --- Test 2: doubly linked prev ---
def test_prev_link():
testcheck.section("Test 2: prev pointer (doubly linked)")
root: Node = Node()
a: Node = Node()
b: Node = Node()
a.value = 1
b.value = 2
root.append(a)
root.append(b)
# b.prev should point to a
bp: Node* = (Node*)(b.prev)
testcheck.check(bp is not None and bp.value == 1,
"b.prev.value=1",
"prev link fail")
# a.prev should be None (first child)
testcheck.check(a.prev is None,
"a.prev=None",
"first prev fail")
# --- Test 3: last_child pointer ---
def test_last_child():
testcheck.section("Test 3: last_child pointer")
root: Node = Node()
a: Node = Node()
b: Node = Node()
a.value = 100
b.value = 200
root.append(a)
lc: Node* = (Node*)(root.last_child)
testcheck.check(lc is not None and lc.value == 100,
"last_child=100 after 1 append",
"last_child fail 1")
root.append(b)
lc = (Node*)(root.last_child)
testcheck.check(lc is not None and lc.value == 200,
"last_child=200 after 2 append",
"last_child fail 2")
# --- Test 4: detach (O(1) unlink) ---
def test_remove():
testcheck.section("Test 4: detach (O(1) unlink)")
root: Node = Node()
a: Node = Node()
b: Node = Node()
c: Node = Node()
a.value = 1
b.value = 2
c.value = 3
root.append(a)
root.append(b)
root.append(c)
# detach middle node b
b.detach()
testcheck.check(root.child_count == 2,
"count=2 after detach",
"detach count fail")
# a.next should point directly to c
an: Node* = (Node*)(a.next)
testcheck.check(an is not None and an.value == 3,
"a.next.value=3",
"detach link fail")
# c.prev should point to a
cp: Node* = (Node*)(c.prev)
testcheck.check(cp is not None and cp.value == 1,
"c.prev.value=1",
"detach prev fail")
# b links should be cleared
testcheck.check(b.parent is None and b.next is None and b.prev is None,
"b cleared",
"b not cleared")
# --- Test 5: remove_child ---
def test_remove_child():
testcheck.section("Test 5: remove_child")
root: Node = Node()
a: Node = Node()
b: Node = Node()
a.value = 10
b.value = 20
root.append(a)
root.append(b)
root.remove_child(a)
testcheck.check(root.child_count == 1,
"count=1 after remove_child",
"remove_child count fail")
fc: Node* = (Node*)(root.child)
testcheck.check(fc is not None and fc.value == 20,
"first child=20",
"remove_child first fail")
# --- Test 6: prepend/insert_before/insert_after ---
def test_insert_ops():
testcheck.section("Test 6: prepend/insert_before/insert_after")
root: Node = Node()
a: Node = Node()
b: Node = Node()
c: Node = Node()
d: Node = Node()
a.value = 1
b.value = 2
c.value = 3
d.value = 4
root.append(a) # [1]
root.append(c) # [1, 3]
root.insert_before(c, b) # [1, 2, 3] insert b before c
root.insert_after(a, d) # [1, 4, 2, 3] insert d after a
# traverse to verify order
cur: Node* = (Node*)(root.child)
v0: int = cur.value
cur = (Node*)(cur.next)
v1: int = cur.value
cur = (Node*)(cur.next)
v2: int = cur.value
cur = (Node*)(cur.next)
v3: int = cur.value
testcheck.check(v0 == 1 and v1 == 4 and v2 == 2 and v3 == 3,
"order 1,4,2,3",
"insert order fail")
testcheck.check(root.child_count == 4,
"count=4",
"insert count fail")
# --- Test 7: child_at + count_children ---
# Node() is stack-allocated; use distinct variables so each node has a unique address.
def test_index_access():
testcheck.section("Test 7: child_at + count_children")
root: Node = Node()
n0: Node = Node()
n1: Node = Node()
n2: Node = Node()
n3: Node = Node()
n4: Node = Node()
n0.value = 0
n1.value = 10
n2.value = 20
n3.value = 30
n4.value = 40
root.append(n0)
root.append(n1)
root.append(n2)
root.append(n3)
root.append(n4)
# child_at
r0: Node* = (Node*)(root.child_at(0))
r2: Node* = (Node*)(root.child_at(2))
r4: Node* = (Node*)(root.child_at(4))
r5: Node* = (Node*)(root.child_at(5))
testcheck.check(r0 is not None and r0.value == 0,
"child_at(0)=0",
"child_at 0 fail")
testcheck.check(r2 is not None and r2.value == 20,
"child_at(2)=20",
"child_at 2 fail")
testcheck.check(r4 is not None and r4.value == 40,
"child_at(4)=40",
"child_at 4 fail")
testcheck.check(r5 is None,
"child_at(5)=None",
"child_at 5 fail")
# count_children
cc: sizet = root.count_children()
testcheck.check(cc == 5,
"count_children=5",
"count_children fail")
# --- Test 8: has_children + sibling traverse ---
def test_sibling_traverse():
testcheck.section("Test 8: has_children + sibling traverse")
root: Node = Node()
testcheck.check(root.has_children() == 0,
"empty has_children=0",
"has_children empty fail")
a: Node = Node()
b: Node = Node()
c: Node = Node()
a.value = 1
b.value = 2
c.value = 3
root.append(a)
root.append(b)
root.append(c)
testcheck.check(root.has_children() == 1,
"has_children=1",
"has_children fail")
# find first/last sibling starting from b
fs: Node* = (Node*)(b.first_sibling())
ls: Node* = (Node*)(b.last_sibling())
testcheck.check(fs is not None and fs.value == 1,
"first_sibling=1",
"first_sibling fail")
testcheck.check(ls is not None and ls.value == 3,
"last_sibling=3",
"last_sibling fail")
# --- Test 9: unlink ---
def test_unlink():
testcheck.section("Test 9: unlink")
root: Node = Node()
a: Node = Node()
b: Node = Node()
a.value = 1
b.value = 2
root.append(a)
root.append(b)
# unlink a: remove from sibling chain and clear parent/child links
a.unlink()
testcheck.check(a.next is None and a.prev is None and a.parent is None,
"a links cleared",
"a links not cleared")
testcheck.check(a.child is None and a.last_child is None and a.child_count == 0,
"a child cleared",
"a child not cleared")
# root should keep only b
testcheck.check(root.child_count == 1,
"root count=1 after unlink",
"root count fail")
# --- Test 10: SListNode (singly linked, OOP) ---
class SNode(linkedlist.SListNode):
value: int
def test_slist():
testcheck.section("Test 10: SListNode (singly linked, OOP)")
n0: SNode = SNode()
n1: SNode = SNode()
n2: SNode = SNode()
n0.value = 100
n1.value = 200
n2.value = 300
# append (O(n)); use n0 as head
head: linkedlist.SListNode* = n0
head = head.append(n1)
head = head.append(n2)
# count
testcheck.check(head.count() == 3,
"count=3",
"count fail")
# at
a0: SNode* = (SNode*)(head.at(0))
a1: SNode* = (SNode*)(head.at(1))
a2: SNode* = (SNode*)(head.at(2))
a3: SNode* = (SNode*)(head.at(3))
testcheck.check(a0 is not None and a0.value == 100,
"at(0)=100",
"at 0 fail")
testcheck.check(a1 is not None and a1.value == 200,
"at(1)=200",
"at 1 fail")
testcheck.check(a2 is not None and a2.value == 300,
"at(2)=300",
"at 2 fail")
testcheck.check(a3 is None,
"at(3)=None",
"at 3 fail")
# remove (drop middle node n1)
head = head.remove(n1)
testcheck.check(head.count() == 2,
"after remove count=2",
"remove count fail")
testcheck.check(n1.Next is None,
"n1.Next cleared",
"n1.Next not cleared")
# after removal a0.Next should point to n2
a0b: SNode* = (SNode*)(a0.Next)
testcheck.check(a0b is not None and a0b.value == 300,
"after remove a0.Next=300",
"a0.Next fail")
# append_after (O(1))
n3: SNode = SNode()
n3.value = 400
tail: linkedlist.SListNode* = n2.append_after(n3)
testcheck.check(tail is n3,
"append_after returns n3",
"append_after fail")
testcheck.check(head.count() == 3,
"after append count=3",
"append count fail")
# --- Test 11: viperlib.sprintf *args forwarding ---
def test_sprintf_vararg():
testcheck.section("Test 11: viperlib.sprintf *args forwarding")
# single %d argument
buf: char* = stdlib.malloc(32)
if buf is None: return
buf[0] = 0
viperlib.sprintf(buf, "key%d", 42)
testcheck.check(string.strcmp(buf, "key42") == 0,
"sprintf key42",
"sprintf key%d fail")
# no argument
buf2: char* = stdlib.malloc(32)
if buf2 is None: return
buf2[0] = 0
viperlib.sprintf(buf2, "hello")
testcheck.check(string.strcmp(buf2, "hello") == 0,
"sprintf hello",
"sprintf no-arg fail")
# multiple arguments
buf3: char* = stdlib.malloc(32)
if buf3 is None: return
buf3[0] = 0
viperlib.sprintf(buf3, "%d+%d=%d", 1, 2, 3)
testcheck.check(string.strcmp(buf3, "1+2=3") == 0,
"sprintf 1+2=3",
"sprintf multi-arg fail")
# --- Test 12: generic GSListNode[T] + GSList[T] ---
# Recursive generic, novirtual flattened fields, generic as field type; local def (no cross-module generic support yet).
novirtual class GSListNode[T]:
Next: T*
novirtual class GSList[T]:
Head: T*
Tail: T*
Count: sizet
def __init__(self):
self.Head = None
self.Tail = None
self.Count = 0
def append(self, node: T):
if node is None: return
node.Next = None
if self.Head is None:
self.Head = node
else:
self.Tail.Next = node
self.Tail = node
self.Count += 1
def count(self) -> sizet:
return self.Count
def at(self, index: sizet) -> T*:
if self.Head is None: return None
cur: T* = self.Head
i: sizet = 0
while cur is not None:
if i == index: return cur
i += 1
cur = cur.Next
return None
class GNode(GSListNode[GNode]):
Value: int
def test_generic_slist():
testcheck.section("Test 12: Generic GSListNode[T] + GSList[T]")
# generic class as field type + construction
lst: GSList[GNode]* = GSList[GNode]()
# recursive generic + NoVTable combo (GNode defined above)
n0: GNode = GNode()
n1: GNode = GNode()
n2: GNode = GNode()
n0.Value = 10
n1.Value = 20
n2.Value = 30
# generic method inheritance
lst.append(n0)
lst.append(n1)
lst.append(n2)
# count (O(1))
testcheck.check(lst.count() == 3,
"GSList.count()=3",
"GSList count fail")
# at (O(n)) returns GNode|CPtr, no downcast needed
a0: GNode* = lst.at(0)
a1: GNode* = lst.at(1)
a2: GNode* = lst.at(2)
a3: GNode* = lst.at(3)
testcheck.check(a0 is not None and a0.Value == 10,
"GSList.at(0)=10",
"GSList at 0 fail")
testcheck.check(a1 is not None and a1.Value == 20,
"GSList.at(1)=20",
"GSList at 1 fail")
testcheck.check(a2 is not None and a2.Value == 30,
"GSList.at(2)=30",
"GSList at 2 fail")
testcheck.check(a3 is None,
"GSList.at(3)=None",
"GSList at 3 fail")
# Next is strongly typed (a0.Next is GNode|CPtr, no cast)
testcheck.check(a0.Next is a1,
"a0.Next is a1 (strong type)",
"a0.Next fail")
testcheck.check(a1.Next is a2,
"a1.Next is a2 (strong type)",
"a1.Next fail")
testcheck.check(a2.Next is None,
"a2.Next is None",
"a2.Next fail")
def main() -> int:
testcheck.begin("NoVTableTest: linkedlist 库(@t.NoVTable OOP 方法 + 字段展平继承)")
test_append()
test_prev_link()
test_last_child()
test_remove()
test_remove_child()
test_insert_ops()
test_index_access()
test_sibling_traverse()
test_unlink()
test_slist()
test_sprintf_vararg()
test_generic_slist()
return testcheck.end()