# test_mail_system_parity.gd —— 40250 游戏内邮箱系统 1:1 纯净回归测试套件 extends SceneTree const MailSystem = preload("res://mail_system.gd") var _passed := 0 var _failed := 0 func _assert(cond: bool, msg: String) -> void: if cond: _passed += 1 print(" [PASS] %s" % msg) else: _failed += 1 printerr(" [FAIL] %s" % msg) func _init() -> void: print("\n=== Running test_mail_system_parity (Direction 4: In-Game Mailbox 1:1) ===") _test_mail_sending_validation() _test_mail_reading_and_unread_count() _test_attachment_claiming() _test_delete_protection() _test_mail_expiry_cleanup() _finish() func _test_mail_sending_validation() -> void: print("\n--- Test 1: Mail Sending Validation & Postage (1000 Yang) ---") var ms := MailSystem.new() var player_data := {"gold": 500} # Less than postage 1000 var inv: Array = [null] # Empty recipient var r1 = ms.send_mail("PlayerA", "", "Title", "Body", player_data, inv) _assert(r1["ok"] == false and r1["reason"] == "EMPTY_RECIPIENT", "Empty recipient rejected") # Insufficient Yang for postage var r2 = ms.send_mail("PlayerA", "PlayerB", "Title", "Body", player_data, inv) _assert(r2["ok"] == false and r2["reason"] == "INSUFFICIENT_YANG", "Blocked when gold < postage fee") # Locked item cannot be mailed player_data["gold"] = 10000 inv[0] = {"vnum": 10, "name": "木剑", "is_locked": true} var r3 = ms.send_mail("PlayerA", "PlayerB", "Title", "Body", player_data, inv, 0) _assert(r3["ok"] == false and r3["reason"] == "ITEM_LOCKED", "Locked item rejected for mailing") # Valid sending without attachment var send_data := {"fired": false, "id": 0} ms.mail_sent.connect(func(mid: int, _s: String, _r: String): send_data["fired"] = true send_data["id"] = mid ) var r4 = ms.send_mail("PlayerA", "PlayerB", "问候信", "你好,这是测试邮件!", player_data, inv) _assert(r4["ok"] == true, "Mail sent successfully") _assert(player_data["gold"] == 9000, "1000 Yang postage deducted (10000 -> 9000)") _assert(send_data["fired"] == true and send_data["id"] == 1, "mail_sent signal fired with id 1") _assert(ms.get_unread_count("PlayerB") == 1, "PlayerB has 1 unread mail") func _test_mail_reading_and_unread_count() -> void: print("\n--- Test 2: Mail Reading & Unread Counter ---") var ms := MailSystem.new() var player_data := {"gold": 10000} var inv: Array = [null] ms.send_mail("Alice", "Bob", "Hello", "World", player_data, inv) _assert(ms.get_unread_count("Bob") == 1, "Initial unread count is 1") var unread_signal := {"fired": false, "count": -1} ms.unread_count_changed.connect(func(_rec: String, cnt: int): unread_signal["fired"] = true unread_signal["count"] = cnt ) # Read mail var res = ms.read_mail(1, "Bob") _assert(res["ok"] == true, "Mail read successfully") _assert(res["mail"]["is_read"] == true, "is_read is true") _assert(ms.get_unread_count("Bob") == 0, "Unread count updated to 0") _assert(unread_signal["fired"] == true and unread_signal["count"] == 0, "unread_count_changed signal fired with 0") # Reading non-existent mail var r_fail = ms.read_mail(999, "Bob") _assert(r_fail["ok"] == false and r_fail["reason"] == "MAIL_NOT_FOUND", "Non-existent mail returns error") func _test_attachment_claiming() -> void: print("\n--- Test 3: Gold & Item Attachment Sealing and Claiming ---") var ms := MailSystem.new() var sender_data := {"gold": 100000} var sender_inv: Array = [ {"vnum": 11299, "name": "黑钢甲+9", "count": 1}, null ] # Send mail with 50,000 Yang and armor in slot 0 var send_res = ms.send_mail( "Sender", "Receiver", "珍贵赠礼", "请收下这件黑钢甲和金币!", sender_data, sender_inv, 0, # attach slot 0 50000 # attach 50,000 gold ) _assert(send_res["ok"] == true, "Mail with attachments sent") _assert(sender_data["gold"] == 49000, "51,000 Yang deducted (50k gold + 1k postage)") _assert(sender_inv[0] == null, "Attached item removed from sender inventory") # Receiver inbox var receiver_data := {"gold": 10000} var receiver_inv: Array = [null, null] var claim_signal := {"fired": false, "id": 0} ms.attachment_claimed.connect(func(mid: int): claim_signal["fired"] = true claim_signal["id"] = mid ) # Claim attachments var claim_res = ms.claim_attachments(1, "Receiver", receiver_data, receiver_inv) _assert(claim_res["ok"] == true, "Attachments claimed successfully") _assert(claim_signal["fired"] == true and claim_signal["id"] == 1, "attachment_claimed signal fired") _assert(receiver_data["gold"] == 60000, "Receiver gold increased by 50,000 (10k -> 60k)") _assert(receiver_inv[0] != null and receiver_inv[0]["vnum"] == 11299, "Attached armor received into inventory") # Double claiming yields nothing var claim_again = ms.claim_attachments(1, "Receiver", receiver_data, receiver_inv) _assert(claim_again["claimed_gold"] == 0 and claim_again["claimed_item"] == null, "No attachments left to claim") func _test_delete_protection() -> void: print("\n--- Test 4: Delete Protection on Unclaimed Attachments ---") var ms := MailSystem.new() var s_data := {"gold": 50000} var s_inv: Array = [{"vnum": 10, "name": "木剑", "count": 1}] ms.send_mail("A", "B", "Item Mail", "Body", s_data, s_inv, 0, 10000) # Trying to delete before claiming attachments var del_blocked = ms.delete_mail(1, "B") _assert(del_blocked["ok"] == false and del_blocked["reason"] == "HAS_UNCLAIMED_ATTACHMENTS", "Deletion blocked while attachments unclaimed") # Claim attachments var b_data := {"gold": 0} var b_inv: Array = [null] ms.claim_attachments(1, "B", b_data, b_inv) # Now deletion succeeds var del_ok = ms.delete_mail(1, "B") _assert(del_ok["ok"] == true, "Mail deleted after attachments claimed") _assert(ms.get_inbox("B").is_empty(), "B inbox is now empty") func _test_mail_expiry_cleanup() -> void: print("\n--- Test 5: 30-Day Expiry Cleanup ---") var ms := MailSystem.new() var s_data := {"gold": 10000} var s_inv: Array = [null] # Send mail at time 0 ms.send_mail("A", "B", "Old Mail", "Body", s_data, s_inv, -1, 0, 0.0) _assert(ms.get_inbox("B").size() == 1, "1 mail exists") # Clean up at day 15 (15 * 86400 = 1296000) -> not expired var c1 = ms.cleanup_expired_mails(1296000.0) _assert(c1 == 0, "0 mails cleaned at 15 days") _assert(ms.get_inbox("B").size() == 1, "Mail still intact") # Clean up at day 31 (31 * 86400 = 2678400) -> expired! var c2 = ms.cleanup_expired_mails(2678400.0) _assert(c2 == 1, "1 mail cleaned after 30 days") _assert(ms.get_inbox("B").size() == 0, "Expired mail was removed") func _finish() -> void: print("\n==========================================") print("Mail System Parity Test Results: %d Passed, %d Failed" % [_passed, _failed]) print("==========================================") if _failed > 0: quit(1) else: quit(0)