extends TestCase ## T-WIN-010:开源声明一致性与完整性 const Credits = preload("res://src/ui/credits.gd") ## 文档 §8.2 模板中的最低 10 项 const REQUIRED_NAMES := [ "MediaPipe", "Three.js", "@pixiv/three-vrm", "Assimp", "Godot Engine", "godot-vrm", "NestJS", "TypeORM", "OkHttp", "bvh", ] func test_credits_cover_documented_minimum_set() -> void: var names: Array = [] for entry in Credits.ENTRIES: names.append(str(entry["name"])) for required in REQUIRED_NAMES: ok(names.has(required), "文档要求的开源项目「%s」已声明" % required) ok(Credits.entry_count() >= 10, "声明条目不少于文档要求的 10 项", "实际 %d" % Credits.entry_count()) func test_every_entry_has_license_and_source_link() -> void: for entry in Credits.ENTRIES: var name := str(entry["name"]) ne(str(entry["license"]), "", "%s 有许可证" % name) var url := str(entry["url"]) ok(url.begins_with("https://"), "%s 的源链接为 https" % name, url) ne(str(entry["usage"]), "", "%s 注明了用途" % name) func test_known_licenses_are_correct() -> void: var expected := { "MediaPipe": "Apache License 2.0", "Godot Engine": "MIT", "Assimp": "BSD-3-Clause", "OkHttp": "Apache License 2.0", "bvh": "MIT", } for entry in Credits.ENTRIES: var name := str(entry["name"]) if expected.has(name): eq(str(entry["license"]), expected[name], "%s 的许可证正确" % name) func test_bbcode_contains_all_entries_and_no_smpl() -> void: var text := Credits.to_bbcode() for entry in Credits.ENTRIES: contains(text, str(entry["name"]), "BBCode 含 %s" % str(entry["name"])) contains(text, str(entry["url"]), "BBCode 含 %s 的链接" % str(entry["name"])) contains(text, "SMPL", "BBCode 明确声明未使用 SMPL") contains(text, "第三方开源项目声明", "BBCode 含声明标题") for key in Credits.CONTRACT_VERSIONS: contains(text, "%s v%s" % [key, Credits.CONTRACT_VERSIONS[key]], "BBCode 含 %s 契约版本" % key) func test_plain_text_export_is_parseable() -> void: var text := Credits.to_plain_text() var lines := text.split("\n") eq(lines.size(), Credits.entry_count(), "纯文本导出行数等于条目数") for line in lines: var parts := line.split(" | ") eq(parts.size(), 3, "每行三段:名称 | 许可证 | 链接") func test_contract_versions_match_snapshot() -> void: # contracts/VERSION 是唯一来源;本端 README/关于页/THIRD_PARTY 都必须与之一致 var file := FileAccess.open("res://contracts/VERSION", FileAccess.READ) if file == null: ok(false, "无法读取 contracts/VERSION 快照") return var content := file.get_as_text() file.close() # 六项各自独立递增,逐项核对(不能用单个常量) for key in Credits.CONTRACT_VERSIONS: contains(content, "%s: %s" % [key, Credits.CONTRACT_VERSIONS[key]], "契约快照 %s 版本一致" % key) # 反向核对:快照里的每一项都必须在代码里有对应常量,避免新增契约漏同步 for line in content.split("\n"): var trimmed := line.strip_edges() if trimmed == "" or trimmed.begins_with("#"): continue var parts := trimmed.split(":") eq(parts.size(), 2, "VERSION 行格式为 name: version(%s)" % trimmed) if parts.size() == 2: var name := parts[0].strip_edges() var version := parts[1].strip_edges() eq(Credits.version_of(name), version, "契约快照新增项 %s 已同步到 Credits" % name)