mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-09-22 17:24:01 +00:00
Address review on the suite and instance tests
- The instance tests run against a real Instance with a real InstanceConfig, matching the controller tests: the spies are sendTo and the server, which record what leaves the instance, so sendRcon passes through the real script command gate. The plugin's config fields are registered so the sync mode is a real field. - Shallow eq is gone and eq compares recursively; the suite is created with Framework.suite(extend_env), which hands the extension a fresh set of stubs per test, so the plugin's env.lua is only the extension. - add_player assigns continuous indexes itself. - The lua fixtures are referenced by role name: assignments take names, and ids in expectations come from the role object. The name lookup in env.R uses a fixture index rather than searching the roles. - Test names format functions as name() and methods as .name(). - Branch coverage filled in: sort tie breaking, the highest role assertion when a player has no roles, has all for the server, the by player default from game.player, deleted assignment records on initialise, set_emit_events with no argument, printing to a role with no holders, role property update validation, the assignment subscription replay, unassignment over the ipc, and a refused removal having nothing to roll back. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e6552a39be
commit
3218351db6
@@ -1,36 +1,37 @@
|
||||
--- Tests for the assignment methods of module/control.lua
|
||||
local Suite = ... --- The suite this file adds its tests to, see test/lua/framework.lua
|
||||
local test, check, eq, deep_eq = Suite.test, Suite.check, Suite.eq, Suite.deep_eq
|
||||
local test, check, eq = Suite.test, Suite.check, Suite.eq
|
||||
|
||||
--- alice is a moderator and bob a regular, with changes sent to the controller
|
||||
local function setup(env)
|
||||
local players = {
|
||||
alice = env.add_player("alice", 1),
|
||||
bob = env.add_player("bob", 2),
|
||||
alice = env.add_player("alice"),
|
||||
bob = env.add_player("bob"),
|
||||
}
|
||||
env.initialise{
|
||||
env.assignment("alice", { 5 }),
|
||||
env.assignment("bob", { 6 }),
|
||||
env.assignment("alice", { "Moderator" }),
|
||||
env.assignment("bob", { "Regular" }),
|
||||
}
|
||||
env.Roles.set_emit_events(true)
|
||||
env.reset_log()
|
||||
return players
|
||||
end
|
||||
|
||||
test("role:assign applies locally and is sent to the controller", function(env)
|
||||
test(".assign() applies locally and is sent to the controller", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Moderator"):assign(players.bob, { by_player_name = "alice" })
|
||||
deep_eq(env.sent, {
|
||||
{ channel = "exp_roles:assignment_update", data = { name = "bob", assign = { 5 } } },
|
||||
local moderator = env.R("Moderator")
|
||||
moderator:assign(players.bob, { by_player_name = "alice" })
|
||||
eq(env.sent, {
|
||||
{ channel = "exp_roles:assignment_update", data = { name = "bob", assign = { moderator.id } } },
|
||||
}, "the assignment is sent to the controller")
|
||||
check(env.R("Moderator"):has_player(players.bob), "the role applies before confirmation")
|
||||
deep_eq(env.events, {
|
||||
check(moderator:has_player(players.bob), "the role applies before confirmation")
|
||||
eq(env.events, {
|
||||
{
|
||||
name = env.Roles.events.on_player_roles_changed,
|
||||
tick = 1,
|
||||
player_index = 2,
|
||||
by_player_index = 1,
|
||||
assigned = { 5 },
|
||||
player_index = players.bob.index,
|
||||
by_player_index = players.alice.index,
|
||||
assigned = { moderator.id },
|
||||
unassigned = {},
|
||||
},
|
||||
}, "the event carries the change")
|
||||
@@ -38,19 +39,26 @@ test("role:assign applies locally and is sent to the controller", function(env)
|
||||
eq(env.sounds, { "bob:utility/achievement_unlocked" }, "the assign sound plays")
|
||||
|
||||
local sd = env.Roles._script_data()
|
||||
eq(sd.local_players.bob, { 5 }, "the role is held locally")
|
||||
eq(sd.pending.bob, { 5 }, "the role is pending")
|
||||
eq(sd.local_players.bob, { moderator.id }, "the role is held locally")
|
||||
eq(sd.pending.bob, { moderator.id }, "the role is pending")
|
||||
|
||||
env.reset_log()
|
||||
env.R("Moderator"):assign(players.bob)
|
||||
moderator:assign(players.bob)
|
||||
check(#env.sent == 0 and #env.events == 0, "assigning a held role is a no-op")
|
||||
end)
|
||||
|
||||
test("receive_assignment_updates releases the local hold once confirmed", function(env)
|
||||
test(".assign() defaults the by player to game.player", function(env)
|
||||
local players = setup(env)
|
||||
game.player = players.alice
|
||||
env.R("Jail"):assign(players.bob, { silent = true })
|
||||
check(env.events[1].by_player_index == players.alice.index, "the acting player is game.player")
|
||||
end)
|
||||
|
||||
test("receive_assignment_updates() releases the local hold once confirmed", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Moderator"):assign(players.bob)
|
||||
env.reset_log()
|
||||
env.Roles.receive_assignment_updates{ env.assignment("bob", { 6, 5 }) }
|
||||
env.Roles.receive_assignment_updates{ env.assignment("bob", { "Regular", "Moderator" }) }
|
||||
check(#env.events == 0 and #env.printed == 0, "a confirmation raises nothing")
|
||||
|
||||
local sd = env.Roles._script_data()
|
||||
@@ -58,44 +66,46 @@ test("receive_assignment_updates releases the local hold once confirmed", functi
|
||||
check(env.R("Moderator"):has_player(players.bob), "the role is still held after confirmation")
|
||||
end)
|
||||
|
||||
test("role:unassign removes a synced role", function(env)
|
||||
test(".unassign() removes a synced role", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Regular"):unassign(players.bob, { by_player_name = "alice", silent = true })
|
||||
deep_eq(env.sent, {
|
||||
{ channel = "exp_roles:assignment_update", data = { name = "bob", unassign = { 6 } } },
|
||||
local regular = env.R("Regular")
|
||||
regular:unassign(players.bob, { by_player_name = "alice", silent = true })
|
||||
eq(env.sent, {
|
||||
{ channel = "exp_roles:assignment_update", data = { name = "bob", unassign = { regular.id } } },
|
||||
}, "the unassignment is sent to the controller")
|
||||
check(not env.R("Regular"):has_player(players.bob), "the role is removed locally")
|
||||
deep_eq(env.events, {
|
||||
check(not regular:has_player(players.bob), "the role is removed locally")
|
||||
eq(env.events, {
|
||||
{
|
||||
name = env.Roles.events.on_player_roles_changed,
|
||||
tick = 1,
|
||||
player_index = 2,
|
||||
by_player_index = 1,
|
||||
player_index = players.bob.index,
|
||||
by_player_index = players.alice.index,
|
||||
assigned = {},
|
||||
unassigned = { 6 },
|
||||
unassigned = { regular.id },
|
||||
},
|
||||
}, "the event carries the change")
|
||||
check(#env.printed == 0, "silent suppresses the announcement")
|
||||
eq(env.sounds, { "bob:utility/game_lost" }, "the unassign sound plays")
|
||||
end)
|
||||
|
||||
test("reject_assignment rolls the assignment back", function(env)
|
||||
test("reject_assignment() rolls the assignment back", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Jail"):assign(players.alice)
|
||||
check(env.R("Jail"):has_player(players.alice), "the role applies before rejection")
|
||||
local jail = env.R("Jail")
|
||||
jail:assign(players.alice)
|
||||
check(jail:has_player(players.alice), "the role applies before rejection")
|
||||
|
||||
env.reset_log()
|
||||
env.Roles.reject_assignment{ name = "alice", role_ids = { 7 } }
|
||||
check(not env.R("Jail"):has_player(players.alice), "the rejected role is rolled back")
|
||||
env.Roles.reject_assignment{ name = "alice", role_ids = { jail.id } }
|
||||
check(not jail:has_player(players.alice), "the rejected role is rolled back")
|
||||
check(#env.sent == 0, "the rollback is not sent to the controller")
|
||||
deep_eq(env.events, {
|
||||
eq(env.events, {
|
||||
{
|
||||
name = env.Roles.events.on_player_roles_changed,
|
||||
tick = 1,
|
||||
player_index = 1,
|
||||
player_index = players.alice.index,
|
||||
by_player_index = 0,
|
||||
assigned = {},
|
||||
unassigned = { 7 },
|
||||
unassigned = { jail.id },
|
||||
},
|
||||
}, "the rollback raises the event")
|
||||
|
||||
@@ -103,44 +113,46 @@ test("reject_assignment rolls the assignment back", function(env)
|
||||
check(sd.local_players.alice == nil and sd.pending.alice == nil, "the rollback clears the local state")
|
||||
end)
|
||||
|
||||
test("role:assign with local_only never reaches the controller", function(env)
|
||||
test(".assign() with local_only never reaches the controller", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Regular"):assign(players.alice, { silent = true, local_only = true })
|
||||
local regular = env.R("Regular")
|
||||
regular:assign(players.alice, { silent = true, local_only = true })
|
||||
check(#env.sent == 0, "the assignment is not sent")
|
||||
check(env.R("Regular"):has_player(players.alice), "the role applies")
|
||||
check(regular:has_player(players.alice), "the role applies")
|
||||
|
||||
local sd = env.Roles._script_data()
|
||||
check(sd.pending.alice == nil, "the role is not pending")
|
||||
eq(sd.local_players.alice, { 6 }, "the role is held locally")
|
||||
eq(sd.local_players.alice, { regular.id }, "the role is held locally")
|
||||
|
||||
env.Roles.receive_assignment_updates{ env.assignment("alice", { 5 }) }
|
||||
check(env.R("Regular"):has_player(players.alice), "the role survives controller updates")
|
||||
env.Roles.receive_assignment_updates{ env.assignment("alice", { "Moderator" }) }
|
||||
check(regular:has_player(players.alice), "the role survives controller updates")
|
||||
|
||||
env.reset_log()
|
||||
env.R("Regular"):unassign(players.alice, { local_only = true })
|
||||
check(not env.R("Regular"):has_player(players.alice) and #env.sent == 0, "removed without sync")
|
||||
regular:unassign(players.alice, { local_only = true })
|
||||
check(not regular:has_player(players.alice) and #env.sent == 0, "removed without sync")
|
||||
end)
|
||||
|
||||
test("role:assign of a higher priority role suppresses the rest", function(env)
|
||||
test(".assign() of a higher priority role suppresses the rest", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Jail"):assign(players.alice, { by_player_name = "<server>", silent = true })
|
||||
local jail = env.R("Jail")
|
||||
jail:assign(players.alice, { by_player_name = "<server>", silent = true })
|
||||
eq(Suite.names(env.Roles.get_player_roles(players.alice)), { "Jail" }, "only the jail role applies")
|
||||
check(env.R("Moderator"):has_player(players.alice), "a suppressed role is still held")
|
||||
check(not env.Roles.player_has_permission(players.alice, "exp_scenario.command.kill"), "permissions are lost")
|
||||
check(not env.Roles.player_has_permission(players.alice, "exp_scenario.gui.readme"), "the default role is lost")
|
||||
check(not env.Roles.player_outranks(players.alice, players.bob), "a jailed player no longer outranks")
|
||||
eq(env.events[1].assigned, { 7 }, "the event lists the jail role")
|
||||
eq(env.events[1].assigned, { jail.id }, "the event lists the jail role")
|
||||
check(#env.events[1].unassigned == 0, "the suppressed roles are not listed as unassigned")
|
||||
|
||||
env.reset_log()
|
||||
env.R("Jail"):unassign(players.alice, { by_player_name = "<server>", silent = true })
|
||||
jail:unassign(players.alice, { by_player_name = "<server>", silent = true })
|
||||
eq(Suite.sorted(Suite.names(env.Roles.get_player_roles(players.alice))), { "Moderator", "Player" },
|
||||
"unjail restores the roles")
|
||||
check(#env.events[1].assigned == 0, "the restored roles are not listed as assigned")
|
||||
eq(env.events[1].unassigned, { 7 }, "the unjail event lists the jail role")
|
||||
eq(env.events[1].unassigned, { jail.id }, "the unjail event lists the jail role")
|
||||
end)
|
||||
|
||||
test("role:assign ignores the server", function(env)
|
||||
test(".assign() ignores the server", function(env)
|
||||
setup(env)
|
||||
env.R("Moderator"):assign(env.server)
|
||||
check(#env.sent == 0 and #env.events == 0, "assigning to the server is a no-op")
|
||||
|
||||
Reference in New Issue
Block a user