mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
219 lines
9.2 KiB
Lua
219 lines
9.2 KiB
Lua
#!/usr/bin/env luajit
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local failed = 0
|
|
local function check(cond, msg)
|
|
if cond then
|
|
print("[ok] " .. msg)
|
|
else
|
|
failed = failed + 1
|
|
print("[FAIL] " .. msg)
|
|
end
|
|
end
|
|
|
|
local function eq(a, b, msg)
|
|
check(a == b, string.format("%s (%s == %s)", msg, tostring(a), tostring(b)))
|
|
end
|
|
|
|
local FakeRelay = require("tests.g3link_fake_relay")
|
|
local RelayTransport = require("src.core.game3.link.relay_transport")
|
|
local Game3Link = require("src.link.Game3Link")
|
|
local Versions = require("src.import.gba.versions")
|
|
|
|
local session = { name = "RED", trainerId = 0x1234, gender = 0 }
|
|
package.loaded["src.core.game3.runtime"] = {
|
|
getSession = function() return session end,
|
|
isActive = function() return true end,
|
|
_game = nil,
|
|
}
|
|
|
|
print("[test] 1. the transport is relay-backed and never pumps the Client")
|
|
local room = FakeRelay.room({ seats = 2, names = { "RED", "BLUE" } })
|
|
local rs0 = room:session(0)
|
|
local t0 = RelayTransport.new(rs0, { client = room:client(0) })
|
|
eq(t0.relay, true, "t.relay is true")
|
|
eq(t0.target, room.id, "t.target is the room id")
|
|
eq(t0.code, nil, "t.code is nil (no codes)")
|
|
t0:update()
|
|
t0:update()
|
|
eq(rs0.updateCalls, nil, "t:update never calls roomSession:update (no double pump)")
|
|
eq(t0:seat(), 0, "seat() reads the room session seat")
|
|
eq(t0:seats(), 2, "seats() reads the room session seat count")
|
|
eq(#t0:players(), 2, "players() lists every seat")
|
|
eq(t0:role(), "host", "role() is host for seat 0")
|
|
eq(t0:seed(), room.seed, "seed() is the relay-dealt seed")
|
|
eq(t0:match(), room.match, "match() is the relay match token")
|
|
eq(t0:peerOnline(1), true, "peerOnline(1) reads the room")
|
|
|
|
print("[test] 2. send strips seat, poll and take tag the sender seat")
|
|
local t1 = RelayTransport.new(room:session(1), { client = room:client(1) })
|
|
t0:send({ type = "game3_link_card", seat = 3, card = { name = "RED" } })
|
|
local got = t1:poll()
|
|
eq(#got, 1, "the peer receives one message")
|
|
eq(got[1] and got[1].seat, 0, "tagged with the sender seat from the envelope, not the spoofed one")
|
|
room:relay({ type = "trade_commit", n = 1, digests = { "a", "b" } })
|
|
local commit = t1:take("trade_commit")
|
|
eq(commit and commit.seat, -1, "relay-authored messages carry seat -1")
|
|
room.inbox[1][#room.inbox[1] + 1] = { type = "spectate", side = "guest", msg = { type = "game3_battle_action", turn = 1 } }
|
|
local unwrapped = t1:poll()[1]
|
|
eq(unwrapped and unwrapped.type, "game3_battle_action", "a legacy spectate envelope is unwrapped")
|
|
eq(unwrapped and unwrapped.seat, 1, "and the side becomes a seat")
|
|
|
|
print("[test] 3. close ends the link only, leave leaves the room")
|
|
t0:close()
|
|
eq(t0.closed, true, "close marks the link closed")
|
|
eq(rs0.left, false, "the room session is untouched")
|
|
eq(#room.players, 2, "both seats are still in the room")
|
|
t0:leave()
|
|
eq(rs0.closeCalls, 1, "leave closes the room session once")
|
|
eq(#room.players, 1, "and the seat leaves the room")
|
|
t0:leave()
|
|
eq(rs0.closeCalls, 1, "a second leave is a no-op")
|
|
|
|
print("[test] 4. the link closes when the room goes away, the Client fails, or a seat leaves")
|
|
local r2 = FakeRelay.room({ seats = 2 })
|
|
local c2 = r2:client(0)
|
|
local ta = RelayTransport.new(r2:session(0), { client = c2 })
|
|
r2:setOnline(1, false)
|
|
ta:update()
|
|
eq(ta.closed, false, "a peer going online:false alone never closes (resume grace)")
|
|
r2:drop(1)
|
|
ta:update()
|
|
eq(ta.closed, true, "a seat listed at match start that left the room closes the link")
|
|
|
|
local r3 = FakeRelay.room({ seats = 2 })
|
|
local tb = RelayTransport.new(r3:session(0), { client = r3:client(0) })
|
|
r3:setState(0, "error")
|
|
tb:update()
|
|
eq(tb.closed, true, "Client error closes the link")
|
|
check(tb.error ~= nil, "and reports the error")
|
|
|
|
local r4 = FakeRelay.room({ seats = 2 })
|
|
local tc = RelayTransport.new(r4:session(0), { client = r4:client(0) })
|
|
r4:setState(0, "offline")
|
|
tc:update()
|
|
eq(tc.closed, true, "Client offline closes the link")
|
|
eq(tc.error, nil, "without an error")
|
|
|
|
local r5 = FakeRelay.room({ seats = 2 })
|
|
local c5 = r5:client(0)
|
|
local td = RelayTransport.new(r5:session(0), { client = c5 })
|
|
local realRoom = c5.room
|
|
c5.room = function()
|
|
local t = realRoom()
|
|
t.room = "r0000000000000bad"
|
|
return t
|
|
end
|
|
td:update()
|
|
eq(td.closed, true, "a different Client room closes the link")
|
|
|
|
print("[test] 5. Game3Link pairs two seats over the relay")
|
|
local game = { data = {}, save = { player = { name = "SAVE" }, options = {} } }
|
|
local host, guest, pairRoom = FakeRelay.pair({ game = game })
|
|
eq(host.myHello.game3.seat, 0, "the host hello carries seat 0")
|
|
eq(guest.myHello.game3.seat, 1, "the guest hello carries seat 1")
|
|
eq(host.role, "host", "seat 0 is the host role")
|
|
eq(guest.role, "guest", "seat 1 is the guest role")
|
|
host:update(0)
|
|
guest:update(0)
|
|
check(host:isReady(), "the host reached ready")
|
|
check(guest:isReady(), "the guest reached ready")
|
|
eq(host.myHello.game3.cacheVersion, Versions.CACHE_VERSION, "the hello carries the cache version")
|
|
eq(host.myHello.name, "RED", "the hello name comes from the live session")
|
|
eq(host.myHello.ruleset, "gen1_faithful", "Handshake.hello reads game.save.options through the view")
|
|
local rows = host:players()
|
|
eq(#rows, 2, "players() has one row per seat")
|
|
eq(rows[1].seat, 0, "sorted by seat")
|
|
eq(rows[1].isLocal, true, "the local row is seat 0 on the host")
|
|
eq(rows[2].role, "guest", "the peer row is the guest")
|
|
eq(guest:peerName(), "RED", "the guest names the host")
|
|
|
|
print("[test] 6. a relay drop is a peer drop, never a room leave by the survivor")
|
|
pairRoom:drop(1)
|
|
host:update(0)
|
|
check(not host:isOpen(), "the survivor's link closed")
|
|
eq(host.reason, "peer_dropped", "reported as a peer drop")
|
|
eq(pairRoom:session(0).closeCalls, nil, "the survivor did not leave the room on its own")
|
|
|
|
print("[test] 7. four seats handshake only after every other hello")
|
|
local quad, links = FakeRelay.links({ seats = 4, game = game })
|
|
links[1]:update(0)
|
|
local early = FakeRelay.room({ seats = 4 })
|
|
local lone = Game3Link.attach(FakeRelay.transport(early, 0), { game = game, seat = 0, seats = 4 })
|
|
local peer1 = Game3Link.attach(FakeRelay.transport(early, 1), { game = game, seat = 1, seats = 4 })
|
|
lone:update(0)
|
|
check(not lone:isReady(), "one hello of three is not enough")
|
|
for _, lk in ipairs(links) do lk:update(0) end
|
|
for i, lk in ipairs(links) do
|
|
check(lk:isReady(), "seat " .. (i - 1) .. " reached ready")
|
|
end
|
|
local four = links[3]:players()
|
|
eq(#four, 4, "players() has four rows")
|
|
eq(four[3].isLocal, true, "seat 2 is the local row on seat 2")
|
|
eq(four[3].role, "seat2", "seat 2 has its seat role")
|
|
eq(links[3].peerHello and links[3].peerHello.game3.seat, 0, "peerHello is seat 0's")
|
|
eq(peer1.seat, 1, "a guest seat stays 1")
|
|
|
|
print("[test] 8. a refused hello on any seat refuses the link")
|
|
local mixed, mlinks = FakeRelay.links({ seats = 2, game = game })
|
|
mixed.inbox[0] = {}
|
|
local stale = Game3Link.hello(game, Game3Link.LINKTYPE.BATTLE)
|
|
stale.game3.cacheVersion = Versions.CACHE_VERSION + 1
|
|
stale.seat = 1
|
|
mixed.inbox[0][1] = stale
|
|
mlinks[1]:update(0)
|
|
check(not mlinks[1]:isOpen(), "a peer on another cache is refused")
|
|
eq(mlinks[1].reason, "cache_version_mismatch", "and says why")
|
|
|
|
print("[test] 9. Game3Link.hello takes a prebuilt player for the launcher")
|
|
local h = Game3Link.hello(game, Game3Link.LINKTYPE.TRADE, { name = "LAUNCH", trainerId = 77, gender = 1 })
|
|
eq(h.name, "LAUNCH", "the override name wins")
|
|
eq(h.game3.trainerId, 77, "the override trainer id wins")
|
|
eq(h.game3.gender, 1, "the override gender wins")
|
|
local r9 = FakeRelay.room({ seats = 2 })
|
|
local prebuilt = Game3Link.attach(FakeRelay.transport(r9, 1), { hello = h, seat = 1, seats = 2 })
|
|
eq(prebuilt.myHello.name, "LAUNCH", "attach sends the prebuilt hello")
|
|
eq(prebuilt.myHello.game3.seat, 1, "stamped with the seat")
|
|
eq(h.game3.seat, nil, "without touching the caller's table")
|
|
|
|
print("[test] 10. loopback stays for tests")
|
|
local lh, lg = Game3Link.loopback({ game = game })
|
|
lh:update(0)
|
|
lg:update(0)
|
|
check(lh:isReady() and lg:isReady(), "the loopback pair still handshakes")
|
|
|
|
print("[test] 11. the cable club has no LAN any more")
|
|
package.loaded["src.core.game3.scripting.space"] = { store = { flags = {}, vars = {} } }
|
|
local Link = require("src.core.game3.link")
|
|
eq(Link.dial, nil, "Link.dial is gone")
|
|
local none, why = Link.open({ address = "203.0.113.1:1" })
|
|
eq(none, nil, "Link.open with an address and no transport opens nothing")
|
|
eq(why, "no_transport", "and says why")
|
|
eq(Link.beginConnect({}), false, "beginConnect never opens an IP screen")
|
|
local LinkMenu = require("src.ui.game3.link_menu")
|
|
eq(LinkMenu.showConnect, nil, "the HOST/JOIN IP screen is gone")
|
|
|
|
print("[test] 12. Link.openRelay adopts the Client room and closeLink leaves it")
|
|
local Client = FakeRelay.client({ state = "online" })
|
|
package.loaded["src.online.Client"] = Client
|
|
local r12 = FakeRelay.room({ seats = 2 })
|
|
Client.bindRoom(r12, 1)
|
|
local rs12 = r12:session(1)
|
|
local opened = Link.openRelay({ game = game })
|
|
check(opened ~= nil, "openRelay attached a link")
|
|
eq(Link.link, opened, "it is the live cable club link")
|
|
eq(opened.seat, 1, "seated from the room session")
|
|
eq(opened._transport.relay, true, "over the relay transport")
|
|
Link.closeLink("done")
|
|
eq(opened.closed, true, "closeLink closed the link")
|
|
eq(rs12.closeCalls, 1, "and then left the room")
|
|
eq(#r12.players, 1, "the seat is gone from the room")
|
|
Link.reset()
|
|
|
|
if failed == 0 then
|
|
print("[pass] relay transport")
|
|
os.exit(0)
|
|
end
|
|
print("[fail] relay transport: " .. failed)
|
|
os.exit(1)
|