# test_offline_bazaar_market_parity.gd —— 40250 单人单机广场离线摆摊与虚拟交易 1:1 回归测试套件 extends SceneTree const OfflineBazaarMarketSystem = preload("res://offline_bazaar_market_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_offline_bazaar_market_parity (Direction 1: Offline Bazaar Market 1:1) ===") _test_npc_stalls_browse_and_buy() _test_buy_validation_errors() _test_player_stall_open() _test_offline_sales_and_revenue() _test_stall_close_and_item_return() _finish() func _test_npc_stalls_browse_and_buy() -> void: print("\n--- Test 1: NPC Stalls Browsing & Purchasing ---") var mkt := OfflineBazaarMarketSystem.new() var stalls = mkt.get_all_stalls() _assert(stalls.size() == 3, "Found 3 default NPC stalls in village square") # Browse Stall 1 (Materials) var b_res = mkt.browse_stall(1) _assert(b_res["ok"] == true and b_res["owner"] == "阿隆", "Browsed Stall 1 (阿隆)") _assert(b_res["items"].size() == 4, "Stall 1 has 4 goods") # Buy Pearl (27993) from Stall 1 var player := {"gold": 2000000} var inv: Array = [] inv.resize(10) for i in range(10): inv[i] = null var buy_sig := {"fired": false, "name": "", "cost": 0} mkt.item_bought_from_stall.connect(func(_sid: int, iname: String, _c: int, cost: int): buy_sig["fired"] = true buy_sig["name"] = iname buy_sig["cost"] = cost ) # Buy 2 pearls: 500,000 * 2 = 1,000,000 gold var buy_res = mkt.buy_from_stall(1, 0, 2, player, inv) _assert(buy_res["ok"] == true, "Purchased 2 pearls") _assert(player["gold"] == 1000000, "Gold deducted 2M -> 1M") _assert(inv[0]["vnum"] == 27993 and inv[0]["count"] == 2, "Pearls placed in slot 0") _assert(mkt.npc_stalls[1]["items"][0]["stock"] == 3, "Stock decreased 5 -> 3") _assert(buy_sig["fired"] == true and buy_sig["name"] == "珍珠", "item_bought_from_stall signal fired") func _test_buy_validation_errors() -> void: print("\n--- Test 2: Purchase Error Validations ---") var mkt := OfflineBazaarMarketSystem.new() var player := {"gold": 100} # Very poor var inv: Array = [null] # Not enough gold var fail_gold = mkt.buy_from_stall(1, 0, 1, player, inv) _assert(fail_gold["ok"] == false and fail_gold["reason"] == "NOT_ENOUGH_GOLD", "Rejected: not enough gold") # Out of stock player["gold"] = 999999999 var fail_stock = mkt.buy_from_stall(1, 0, 999, player, inv) _assert(fail_stock["ok"] == false and fail_stock["reason"] == "OUT_OF_STOCK", "Rejected: out of stock") # Full inventory var full_inv := [{"vnum": 1}] var fail_inv = mkt.buy_from_stall(1, 0, 1, player, full_inv) _assert(fail_inv["ok"] == false and fail_inv["reason"] == "INVENTORY_FULL", "Rejected: inventory full") func _test_player_stall_open() -> void: print("\n--- Test 3: Opening Private Player Stall (50200 Bundle) ---") var mkt := OfflineBazaarMarketSystem.new() var inv: Array = [ {"vnum": OfflineBazaarMarketSystem.ITEM_BUNDLE_VNUM, "name": "摆摊包袱", "count": 1}, {"vnum": 10, "name": "巨剑+9", "count": 1}, {"vnum": 27003, "name": "红色药水(特大)", "count": 100} ] var open_sig := {"fired": false, "title": "", "count": 0} mkt.player_stall_opened.connect(func(t: String, c: int): open_sig["fired"] = true open_sig["title"] = t open_sig["count"] = c ) # Try open without bundle var no_bundle_inv: Array = [{"vnum": 10, "count": 1}] var fail_bundle = mkt.open_player_stall("我的摊位", [{"slot": 0, "price": 1000}], no_bundle_inv, true) _assert(fail_bundle["ok"] == false and fail_bundle["reason"] == "NEED_BUNDLE_ITEM", "Rejected without bundle") # Open stall with bundle and 2 items var items_to_list := [ {"slot": 1, "price": 500000, "count": 1}, {"slot": 2, "price": 200, "count": 50} # sell 50 out of 100 ] var res = mkt.open_player_stall("【东方极速特惠商铺】", items_to_list, inv, true) _assert(res["ok"] == true, "Player stall opened") _assert(inv[0] == null, "Bundle item (50200) consumed") _assert(inv[1] == null, "Listed Sword removed from inventory slot 1") _assert(inv[2]["count"] == 50, "Potion count halved in inventory (100 - 50 = 50)") _assert(mkt.player_stall["is_open"] == true, "Stall is open") _assert(mkt.player_stall["items"].size() == 2, "2 goods listed in stall") _assert(open_sig["fired"] == true and open_sig["count"] == 2, "player_stall_opened signal fired") func _test_offline_sales_and_revenue() -> void: print("\n--- Test 4: Simulated Offline Sales & Revenue Collection ---") var mkt := OfflineBazaarMarketSystem.new() var inv: Array = [ {"vnum": 50200, "count": 1}, {"vnum": 28430, "name": "战士灵石+4", "count": 1} ] mkt.open_player_stall("【灵石专卖】", [{"slot": 1, "price": 1000000, "count": 1}], inv, true) _assert(mkt.player_stall["items"].size() == 1, "1 item listed") # Simulate 30 minutes of offline time var sim = mkt.simulate_offline_sales(30.0) _assert(sim["sold_count"] == 1, "Stone sold during simulated offline time") _assert(mkt.player_stall["revenue"] == 1000000, "1M gold earned in stall revenue") _assert(mkt.player_stall["items"].is_empty(), "Stall inventory now empty") # Collect revenue var player := {"gold": 50000} var col_res = mkt.collect_stall_revenue(player) _assert(col_res["ok"] == true and player["gold"] == 1050000, "Collected revenue into player wallet") _assert(mkt.player_stall["revenue"] == 0, "Stall revenue reset to 0") func _test_stall_close_and_item_return() -> void: print("\n--- Test 5: Closing Stall & Returning Unsold Items ---") var mkt := OfflineBazaarMarketSystem.new() var inv: Array = [ {"vnum": 50200, "count": 1}, {"vnum": 11299, "name": "黑铁战甲+9", "count": 1} ] mkt.open_player_stall("【神装铺】", [{"slot": 1, "price": 10000000, "count": 1}], inv, true) var close_sig := {"fired": false, "rev": -1} mkt.player_stall_closed.connect(func(rev: int): close_sig["fired"] = true close_sig["rev"] = rev ) # Close stall immediately without sales var player := {"gold": 0} var close_res = mkt.close_player_stall(inv, player) _assert(close_res["ok"] == true, "Stall closed successfully") _assert(mkt.player_stall["is_open"] == false, "Stall is no longer open") _assert(close_sig["fired"] == true and close_sig["rev"] == 0, "player_stall_closed signal fired") _assert(inv[0]["vnum"] == 11299, "Unsold armor safely returned to first empty inventory slot") func _finish() -> void: print("\n==========================================") print("Offline Bazaar Market Parity Tests Finished:") print("Passed: %d, Failed: %d" % [_passed, _failed]) print("==========================================") if _failed > 0: printerr("FAILED: Some tests did not pass.") quit(1) else: print("SUCCESS: All Offline Bazaar Market parity tests passed!") quit(0)