mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-06 13:33:55 -07:00
Wire command zone menu, harden counter command handling, and expand tests
- Connect aMoveToCommandZone to cmMoveToCommandZone; the menu item was
added, shown, and shortcut-bound but never wired, so it did nothing
- Extract evaluateModifyCounter() and route cmdIncCounter/cmdSetCounter
through it, replacing isCommandZoneCounterBlocked; reject inc/set on
an inactive tax counter so a hidden counter cannot accumulate value
- Reject reserved tax counter names in cmdCreateCounter to prevent a
client from spoofing a system tax counter via a user-created counter
- Route AbstractCounter::valueChanged through the virtual setValue() so
CommanderTaxCounter clamps and refreshes its tooltip on value changes
- Deduplicate actPlayAndIncreaseTax/actPlayAndIncreasePartnerTax into a
single playAndIncreaseTax(counterId) helper
- Move MINIMUM_STACKING_HEIGHT from CommandZone to the PlayerGraphicsItem
layout code, its only consumer
- Remove unused AbstractCounter forward declaration from player_logic.h
- Add EvaluateModifyCounter tests and PartnerTax cases for
evaluateSetCounterActive
- Pin the FirstUserId floor in new_counter_id_test using ids 3 and 5 so
a naive "highest id + 1" regression fails the test
This commit is contained in:
parent
0bfb0f4131
commit
bc09a19b50
11 changed files with 172 additions and 47 deletions
|
|
@ -1,7 +1,8 @@
|
|||
// Unit tests for the pure authorization logic extracted from the counter command
|
||||
// handlers. Server_Player::evaluateDelCounter() and evaluateSetCounterActive() are
|
||||
// static and depend only on their arguments, so each guard branch can be exercised
|
||||
// directly without a started game, network stack, or player fixture.
|
||||
// handlers. Server_Player::evaluateDelCounter(), evaluateSetCounterActive() and
|
||||
// evaluateModifyCounter() are static and depend only on their arguments, so each
|
||||
// guard branch can be exercised directly without a started game, network stack, or
|
||||
// player fixture.
|
||||
|
||||
#include "game/server_counter.h"
|
||||
#include "game/server_player.h"
|
||||
|
|
@ -158,6 +159,89 @@ TEST(EvaluateSetCounterActive, AllowsDisablingWhenCounterIsZero)
|
|||
Response::RespOk);
|
||||
}
|
||||
|
||||
// PartnerTax is the second reserved tax counter and must flow through the same auth
|
||||
// path as CommanderTax: enabling is always permitted...
|
||||
TEST(EvaluateSetCounterActive, AllowsEnablingPartnerTax)
|
||||
{
|
||||
Server_Counter counter = makeCounter(CounterIds::PartnerTax, 0);
|
||||
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::PartnerTax, &counter,
|
||||
/*requestedActive=*/true),
|
||||
Response::RespOk);
|
||||
}
|
||||
|
||||
// ...and disabling is rejected while it still holds accumulated tax.
|
||||
TEST(EvaluateSetCounterActive, RejectsDisablingPartnerTaxWhenAccumulated)
|
||||
{
|
||||
Server_Counter counter = makeCounter(CounterIds::PartnerTax, 2);
|
||||
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::PartnerTax, &counter,
|
||||
/*requestedActive=*/false),
|
||||
Response::RespContextError);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// evaluateModifyCounter (shared by cmdIncCounter / cmdSetCounter)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// No counter may be modified before the game starts.
|
||||
TEST(EvaluateModifyCounter, RejectsWhenGameNotStarted)
|
||||
{
|
||||
Server_Counter counter = makeCounter(UserCounterId, 0);
|
||||
EXPECT_EQ(Server_Player::evaluateModifyCounter(/*gameStarted=*/false, false, /*commandZoneEnabled=*/true,
|
||||
UserCounterId, &counter),
|
||||
Response::RespGameNotStarted);
|
||||
}
|
||||
|
||||
// A conceded player may no longer modify counters.
|
||||
TEST(EvaluateModifyCounter, RejectsWhenPlayerConceded)
|
||||
{
|
||||
Server_Counter counter = makeCounter(UserCounterId, 0);
|
||||
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, /*playerConceded=*/true, true, UserCounterId, &counter),
|
||||
Response::RespContextError);
|
||||
}
|
||||
|
||||
// An ordinary user counter can be modified regardless of command-zone state.
|
||||
TEST(EvaluateModifyCounter, AllowsUserCounter)
|
||||
{
|
||||
Server_Counter counter = makeCounter(UserCounterId, 0);
|
||||
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/false, UserCounterId, &counter),
|
||||
Response::RespOk);
|
||||
}
|
||||
|
||||
// A non-existent counter is reported as not found.
|
||||
TEST(EvaluateModifyCounter, RejectsMissingCounter)
|
||||
{
|
||||
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, true, UserCounterId, nullptr),
|
||||
Response::RespNameNotFound);
|
||||
}
|
||||
|
||||
// A tax counter may not be modified outside a Commander game (command zone disabled).
|
||||
TEST(EvaluateModifyCounter, RejectsTaxCounterWhenCommandZoneDisabled)
|
||||
{
|
||||
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 0);
|
||||
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/false, CounterIds::CommanderTax,
|
||||
&counter),
|
||||
Response::RespContextError);
|
||||
}
|
||||
|
||||
// An inactive (hidden) tax counter must not accumulate value behind the scenes.
|
||||
TEST(EvaluateModifyCounter, RejectsInactiveTaxCounter)
|
||||
{
|
||||
Server_Counter counter = makeCounter(CounterIds::PartnerTax, 0);
|
||||
(void)counter.setActive(false);
|
||||
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/true, CounterIds::PartnerTax,
|
||||
&counter),
|
||||
Response::RespContextError);
|
||||
}
|
||||
|
||||
// An active tax counter in a Commander game may be modified.
|
||||
TEST(EvaluateModifyCounter, AllowsActiveTaxCounter)
|
||||
{
|
||||
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 0);
|
||||
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/true, CounterIds::CommanderTax,
|
||||
&counter),
|
||||
Response::RespOk);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
|
|
|||
|
|
@ -41,13 +41,15 @@ TEST(NewCounterId, ReturnsFirstUserIdWhenNoCounters)
|
|||
EXPECT_EQ(f.player.newCounterId(), CounterIds::FirstUserId);
|
||||
}
|
||||
|
||||
// Reserved ids 0-9 (standard player counters and the commander tax counters) must
|
||||
// not drag a new user counter down into the reserved range.
|
||||
// Reserved ids must not drag a new user counter down into the reserved range. The
|
||||
// ids here (3 and 5) are chosen so a naive "highest id + 1" implementation would
|
||||
// return 6 (inside the reserved range) and fail this test; only the FirstUserId
|
||||
// floor yields the correct 10, so this pins the floor against regression.
|
||||
TEST(NewCounterId, SkipsReservedRangeWhenOnlyReservedCountersExist)
|
||||
{
|
||||
PlayerFixture f;
|
||||
f.player.addCounter(new Server_Counter(3, "g", color(), 20, 0));
|
||||
f.player.addCounter(new Server_Counter(CounterIds::PartnerTax, CounterNames::PartnerTax, color(), 20, 0));
|
||||
f.player.addCounter(new Server_Counter(5, "h", color(), 20, 0));
|
||||
EXPECT_EQ(f.player.newCounterId(), CounterIds::FirstUserId);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue