204 lines
5.8 KiB
GDScript
204 lines
5.8 KiB
GDScript
extends Node
|
|
## 服务器更新同步属性测试
|
|
## Feature: godot-ai-town-game, Property 30: 服务器更新同步
|
|
|
|
const TEST_ITERATIONS = 50
|
|
|
|
# 测试结果统计
|
|
var test_results = {
|
|
"passed": 0,
|
|
"failed": 0,
|
|
"errors": []
|
|
}
|
|
|
|
func _ready():
|
|
print("\n=== Property Test: Server Update Synchronization ===")
|
|
await test_property_server_update_sync()
|
|
print_results()
|
|
print("=== Property Test Completed ===\n")
|
|
|
|
## Feature: godot-ai-town-game, Property 30: 服务器更新同步
|
|
func test_property_server_update_sync():
|
|
"""
|
|
属性测试:服务器更新同步
|
|
对于任意服务器推送的更新消息,客户端应该实时更新本地游戏状态以反映服务器的变化
|
|
|
|
本测试验证:
|
|
1. 消息协议的序列化/反序列化正确性
|
|
2. 不同类型消息的数据完整性
|
|
3. 消息格式的有效性
|
|
|
|
验证需求: 12.5
|
|
"""
|
|
print("\n[Property Test] Testing server update synchronization...")
|
|
print("Running ", TEST_ITERATIONS, " iterations...")
|
|
|
|
# 测试不同类型的服务器更新消息
|
|
var message_types = [
|
|
MessageProtocol.MessageType.CHARACTER_MOVE,
|
|
MessageProtocol.MessageType.CHARACTER_STATE,
|
|
MessageProtocol.MessageType.WORLD_STATE
|
|
]
|
|
|
|
for i in range(TEST_ITERATIONS):
|
|
# 随机选择消息类型
|
|
var msg_type = message_types[randi() % message_types.size()]
|
|
|
|
# 生成随机测试数据
|
|
var original_message = _generate_test_message(msg_type)
|
|
|
|
# 模拟服务器发送:序列化消息
|
|
var serialized = MessageProtocol.serialize(original_message)
|
|
|
|
# 模拟客户端接收:反序列化消息
|
|
var received_message = MessageProtocol.deserialize(serialized)
|
|
|
|
await get_tree().process_frame
|
|
|
|
# 验证消息是否正确接收
|
|
if received_message.is_empty():
|
|
test_results["failed"] += 1
|
|
test_results["errors"].append({
|
|
"iteration": i + 1,
|
|
"type": "deserialization_failed",
|
|
"original": original_message,
|
|
"serialized": serialized
|
|
})
|
|
continue
|
|
|
|
# 验证消息格式
|
|
if not MessageProtocol.validate_message(received_message):
|
|
test_results["failed"] += 1
|
|
test_results["errors"].append({
|
|
"iteration": i + 1,
|
|
"type": "invalid_message_format",
|
|
"message": received_message
|
|
})
|
|
continue
|
|
|
|
# 验证数据完整性
|
|
var data_matches = _verify_message_data(original_message, received_message)
|
|
|
|
if data_matches:
|
|
test_results["passed"] += 1
|
|
else:
|
|
test_results["failed"] += 1
|
|
test_results["errors"].append({
|
|
"iteration": i + 1,
|
|
"type": "data_mismatch",
|
|
"expected": original_message,
|
|
"actual": received_message
|
|
})
|
|
|
|
func _generate_test_message(msg_type: MessageProtocol.MessageType) -> Dictionary:
|
|
"""生成测试消息"""
|
|
var data = {}
|
|
|
|
match msg_type:
|
|
MessageProtocol.MessageType.CHARACTER_MOVE:
|
|
data = {
|
|
"character_id": "char_" + str(randi()),
|
|
"position": {
|
|
"x": randf_range(0, 1000),
|
|
"y": randf_range(0, 1000)
|
|
},
|
|
"direction": {
|
|
"x": randf_range(-1, 1),
|
|
"y": randf_range(-1, 1)
|
|
}
|
|
}
|
|
|
|
MessageProtocol.MessageType.CHARACTER_STATE:
|
|
data = {
|
|
"character_id": "char_" + str(randi()),
|
|
"is_online": randi() % 2 == 0,
|
|
"position": {
|
|
"x": randf_range(0, 1000),
|
|
"y": randf_range(0, 1000)
|
|
}
|
|
}
|
|
|
|
MessageProtocol.MessageType.WORLD_STATE:
|
|
var num_characters = randi() % 5 + 1
|
|
var characters = []
|
|
for j in range(num_characters):
|
|
characters.append({
|
|
"id": "char_" + str(j),
|
|
"name": "Character" + str(j),
|
|
"position": {
|
|
"x": randf_range(0, 1000),
|
|
"y": randf_range(0, 1000)
|
|
},
|
|
"is_online": randi() % 2 == 0
|
|
})
|
|
data = {
|
|
"characters": characters
|
|
}
|
|
|
|
return MessageProtocol.create_message(msg_type, data)
|
|
|
|
func _verify_message_data(expected: Dictionary, actual: Dictionary) -> bool:
|
|
"""验证消息数据是否匹配"""
|
|
# 验证消息类型
|
|
if expected.get("type") != actual.get("type"):
|
|
print(" Type mismatch: ", expected.get("type"), " vs ", actual.get("type"))
|
|
return false
|
|
|
|
# 验证数据字段存在
|
|
if not actual.has("data"):
|
|
print(" Missing data field")
|
|
return false
|
|
|
|
# 基本验证:检查关键字段
|
|
var expected_data = expected.get("data", {})
|
|
var actual_data = actual.get("data", {})
|
|
|
|
# 根据消息类型验证特定字段
|
|
var msg_type_str = expected.get("type")
|
|
|
|
if msg_type_str == "character_move":
|
|
var char_id_match = expected_data.get("character_id") == actual_data.get("character_id")
|
|
var pos_match = _compare_positions(expected_data.get("position"), actual_data.get("position"))
|
|
return char_id_match and pos_match
|
|
|
|
elif msg_type_str == "character_state":
|
|
var char_id_match = expected_data.get("character_id") == actual_data.get("character_id")
|
|
var online_match = expected_data.get("is_online") == actual_data.get("is_online")
|
|
return char_id_match and online_match
|
|
|
|
elif msg_type_str == "world_state":
|
|
var expected_chars = expected_data.get("characters", [])
|
|
var actual_chars = actual_data.get("characters", [])
|
|
return expected_chars.size() == actual_chars.size()
|
|
|
|
return true
|
|
|
|
func _compare_positions(pos1: Dictionary, pos2: Dictionary) -> bool:
|
|
"""比较两个位置是否相近"""
|
|
if not pos1 or not pos2:
|
|
return false
|
|
|
|
var x1 = pos1.get("x", 0.0)
|
|
var y1 = pos1.get("y", 0.0)
|
|
var x2 = pos2.get("x", 0.0)
|
|
var y2 = pos2.get("y", 0.0)
|
|
|
|
return abs(x1 - x2) < 0.01 and abs(y1 - y2) < 0.01
|
|
|
|
func print_results():
|
|
"""打印测试结果"""
|
|
print("\n=== Test Results ===")
|
|
print("Total iterations: ", TEST_ITERATIONS)
|
|
print("Passed: ", test_results["passed"])
|
|
print("Failed: ", test_results["failed"])
|
|
|
|
if test_results["failed"] > 0:
|
|
print("\n❌ FAILED: Some iterations failed")
|
|
print("First 5 errors:")
|
|
for i in range(min(5, test_results["errors"].size())):
|
|
var error = test_results["errors"][i]
|
|
print(" Error ", i + 1, ": ", error)
|
|
else:
|
|
print("\n✅ PASSED: All server updates synchronized correctly")
|
|
print("Property 30 validated: Server updates are properly received and processed")
|