Files
gplan-2/game/tests/unit/data_config/rng_service_test.gd
T

80 lines
3.4 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# tests/unit/data_config/rng_service_test.gd — 统一随机流单元测试:单盐派生确定性/计数器账本/标签词表封闭
# 运行:godot --headless --path game --script res://tests/unit/data_config/rng_service_test.gd
# 红线:零自建 RNG——本测试只经 RngService 统一流取数(确定性契约:同种子逐位复现)。
# 测试种子为夹具基建值(非玩法数值),与冒烟黄金向量锚(smoke_all m=42 scope 0-4)分工:本文件测
# 「同种子两实例逐位一致」的相对确定性,绝对向量锚归冒烟单点,避免双处维护同一常量。
extends SceneTree
const RngServiceScript := preload("res://core/rng_service.gd")
const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:_check/汇总退出样板单点
const TEST_SEED := 20260928 # 夹具种子(任意固定值;语义 = 可复现性,非玩法数值)
func _init() -> void:
_test_derive_determinism()
_test_counter_ledger()
_test_stream_draw_determinism()
_test_negative_seed_normalization()
quit(Kit.finish("rng_service_test"))
func _fresh_service():
var rng = RngServiceScript.new()
rng.set_master_seed(TEST_SEED)
return rng
# 单盐派生纯函数:两全新实例同种子逐位一致(derive_at 不推计数器——纯函数契约)
func _test_derive_determinism() -> void:
var a = _fresh_service()
var b = _fresh_service()
var same := true
for scope in range(8):
if a.derive_at(scope) != b.derive_at(scope):
same = false
Kit.check("同种子两实例 derive_at(0..7) 逐位一致", same)
var a2 = _fresh_service()
var before: int = a2.counter()
a2.derive_at(0)
Kit.check("derive_at 为纯函数不推计数器", a2.counter() == before)
# 全局取数计数器:唯一账本——open_stream 逐次 +1(scope 单调)
func _test_counter_ledger() -> void:
var rng = _fresh_service()
var c0: int = rng.counter()
rng.open_stream("armor_roll")
var c1: int = rng.counter()
rng.open_stream("armor_roll")
var c2: int = rng.counter()
Kit.check("open_stream 逐次推进全局计数器(+1/次)", c1 == c0 + 1 and c2 == c0 + 2)
# 用途标签只进事件日志不参与派生——同 scope 同派生种子(ADR-0007 裁丙口径)
var rng_x = _fresh_service()
var rng_y = _fresh_service()
var s1: int = int(rng_x.open_stream("board_gen").seed)
var s2: int = int(rng_y.open_stream("reward_roll").seed)
Kit.check("同 scope 异用途标签派生种子一致(标签不参与派生)", s1 == s2)
# 同种子两实例同标签流的实际取数序列逐位一致(回放确定性契约——存档快照=主种子+计数器的前提)
func _test_stream_draw_determinism() -> void:
var faces := 20 # d20 探针面数(夹具值,非玩法表值——只用于产生可比较序列)
var a = _fresh_service()
var b = _fresh_service()
var same := true
for i in range(12):
var ra: int = a.open_stream("armor_roll").randi_range(1, faces)
var rb: int = b.open_stream("armor_roll").randi_range(1, faces)
if ra != rb:
same = false
Kit.check("同种子两实例同标签流取数 12 次逐位一致", same)
# 负输入 abs 归一化(警告通道)——|−s| 与 s 同派生
func _test_negative_seed_normalization() -> void:
var pos = _fresh_service()
var neg = RngServiceScript.new()
neg.set_master_seed(-TEST_SEED)
Kit.check("负种子 abs 归一化后派生与正种子一致", pos.derive_at(0) == neg.derive_at(0))