import stdio
import t, c
import string
from inherit_test import Animal, Dog


# ============================================================
# 虚分派测试：通过虚表指针验证虚分派机制
#
# 本测试验证：方法调用通过对象的 __vtable__ 字段进行虚分派，
# 而非通过变量声明类型直接调用。
#
# 测试方法：
# 1. 创建 Animal 对象 a（Animal 虚表，Speak 返回 0）
# 2. 创建 Dog 对象 d
# 3. 用内联汇编将 d 的虚表指针复制到 a
# 4. 调用 a.Speak() — 应返回 1（Dog.Speak），证明虚分派生效
#
# 如果是直接调用（非虚分派），a.Speak() 会调用 Animal.Speak 返回 0
#
# 注意：Animal 和 Dog 类从 inherit_test.py 导入（命名空间隔离）
# ============================================================


def virtual_dispatch_test() -> int:
    stdio.printf("vdispatch: === Test Start ===\n")

    # 创建对象
    a: Animal = Animal(42)
    d: Dog = Dog(100, 7)

    # ============================================================
    # 测试 1: 直接分派（基线验证）
    # ============================================================
    stdio.printf("vdispatch: === Test 1: Direct Dispatch ===\n")

    a_speak: int = a.Speak()
    stdio.printf("vdispatch: a.Speak()=%d (expected 0)\n", a_speak)
    if a_speak != 0:
        stdio.printf("[FAIL] a.Speak()=%d expected 0\n", a_speak)
        return 1

    d_speak: int = d.Speak()
    stdio.printf("vdispatch: d.Speak()=%d (expected 1)\n", d_speak)
    if d_speak != 1:
        stdio.printf("[FAIL] d.Speak()=%d expected 1\n", d_speak)
        return 1

    # ============================================================
    # 测试 2: 虚分派验证（复制虚表指针）
    #
    # 将 Dog 的虚表指针复制到 Animal 对象 a
    # 虚表指针位于结构体偏移 0（__vtable__ 字段）
    # 复制后 a.Speak() 应通过虚表分发到 Dog.Speak（返回 1）
    # ============================================================
    stdio.printf("vdispatch: === Test 2: Virtual Dispatch ===\n")

    # 使用 string.memcpy 复制虚表指针（8字节，结构体偏移0）
    # 将 d 的虚表指针复制到 a，使 a.Speak() 分发到 Dog.Speak
    string.memcpy(c.Addr(a), c.Addr(d), 8)

    a_speak2: int = a.Speak()
    stdio.printf("vdispatch: a.Speak()=%d (expected 1 after vtable copy)\n", a_speak2)
    if a_speak2 != 1:
        stdio.printf("[FAIL] a.Speak()=%d expected 1 after vtable copy\n", a_speak2)
        return 1

    # ============================================================
    # 测试 3: GetName 验证（未被覆盖的虚方法）
    #
    # Dog 没有覆盖 GetName，Dog 虚表中 GetName 槽位指向 Animal.GetName
    # a.GetName() 应返回 a.name (42)，证明虚表槽位一致性
    # ============================================================
    stdio.printf("vdispatch: === Test 3: GetName After VTable Copy ===\n")

    a_name: int = a.GetName()
    stdio.printf("vdispatch: a.GetName()=%d (expected 42)\n", a_name)
    if a_name != 42:
        stdio.printf("[FAIL] a.GetName()=%d expected 42\n", a_name)
        return 1

    stdio.printf("vdispatch: === All Tests Passed ===\n")
    return 0
