Test framework improves:

* added command to check graveyard count command;
* added wrong cast/activate command auto-checks in strict mode;
This commit is contained in:
Oleg Agafonov 2020-06-01 09:37:17 +04:00
parent 3333cf3287
commit e7684e4bba
5 changed files with 137 additions and 33 deletions

View file

@ -18,14 +18,23 @@ public class IrencragFeatTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Irencrag Feat", 1); addCard(Zone.HAND, playerA, "Irencrag Feat", 1);
addCard(Zone.HAND, playerA, "Dwarven Trader", 2); addCard(Zone.HAND, playerA, "Dwarven Trader", 2);
// 1
checkPlayableAbility("can cast before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// 2
checkPlayableAbility("can cast after feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// 3
checkPlayableAbility("can't cast after feat 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", false);
setStrictChooseMode(true); setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
//assertAllCommandsUsed(); // second trader must be restricted to cast assertAllCommandsUsed();
assertHandCount(playerA, "Dwarven Trader", 1); assertHandCount(playerA, "Dwarven Trader", 1);
assertPermanentCount(playerA, "Dwarven Trader", 1); assertPermanentCount(playerA, "Dwarven Trader", 1);
@ -38,16 +47,32 @@ public class IrencragFeatTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Irencrag Feat", 1); addCard(Zone.HAND, playerA, "Irencrag Feat", 1);
addCard(Zone.HAND, playerA, "Dwarven Trader", 4); addCard(Zone.HAND, playerA, "Dwarven Trader", 4);
// 1
checkPlayableAbility("can cast before feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// 2
checkPlayableAbility("can cast before feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// 3
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// 4
checkPlayableAbility("can cast after feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// 5
checkPlayableAbility("can't cast after feat 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", false);
setStrictChooseMode(true); setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
//assertAllCommandsUsed(); // second trader must be restricted to cast assertAllCommandsUsed();
assertHandCount(playerA, "Dwarven Trader", 1); assertHandCount(playerA, "Dwarven Trader", 1);
assertPermanentCount(playerA, "Dwarven Trader", 3); assertPermanentCount(playerA, "Dwarven Trader", 3);
@ -59,6 +84,7 @@ public class IrencragFeatTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Irencrag Feat", 1); addCard(Zone.HAND, playerA, "Irencrag Feat", 1);
addCard(Zone.HAND, playerA, "Lightning Bolt", 4); addCard(Zone.HAND, playerA, "Lightning Bolt", 4);
// no restrictions for stack
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat");
@ -80,17 +106,25 @@ public class IrencragFeatTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Irencrag Feat", 1); addCard(Zone.HAND, playerA, "Irencrag Feat", 1);
addCard(Zone.HAND, playerA, "Lightning Bolt", 4); addCard(Zone.HAND, playerA, "Lightning Bolt", 4);
// on stack before
checkPlayableAbility("can cast before feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
checkPlayableAbility("can cast before feat 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
// feat
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// after resolve
checkPlayableAbility("can cast after feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); checkPlayableAbility("can't cast after feat 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", false);
setStrictChooseMode(true); setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
//assertAllCommandsUsed(0); // second bolt must be restricted to cast assertAllCommandsUsed();
assertHandCount(playerA, "Lightning Bolt", 4 - 3); assertHandCount(playerA, "Lightning Bolt", 4 - 3);
assertLife(playerB, 20 - 3 * 3); assertLife(playerB, 20 - 3 * 3);

View file

@ -39,14 +39,20 @@ public class AdventureCardsTest extends CardTestPlayerBase {
@Test @Test
public void testCantCastTreatsToShareTwice() { public void testCantCastTreatsToShareTwice() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.HAND, playerA, "Curious Pair"); addCard(Zone.HAND, playerA, "Curious Pair");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
checkPlayableAbility("can play on first", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Treats to Share", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Treats to Share"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Treats to Share");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Treats to Share");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPlayableAbility("can't play on second", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Treats to Share", false);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertActionsCount(playerA, 1); assertAllCommandsUsed();
assertHandCount(playerA, 0); assertHandCount(playerA, 0);
assertPermanentCount(playerA, "Food", 1); assertPermanentCount(playerA, "Food", 1);
assertExileCount(playerA, "Curious Pair", 1); assertExileCount(playerA, "Curious Pair", 1);
@ -430,18 +436,21 @@ public class AdventureCardsTest extends CardTestPlayerBase {
@Test @Test
public void testCantCastCuriousPairWithMelek() { public void testCantCastCuriousPairWithMelek() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Melek, Izzet Paragon");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
removeAllCardsFromLibrary(playerA); removeAllCardsFromLibrary(playerA);
addCard(Zone.BATTLEFIELD, playerA, "Melek, Izzet Paragon");
//
addCard(Zone.LIBRARY, playerA, "Curious Pair"); addCard(Zone.LIBRARY, playerA, "Curious Pair");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curious Pair"); checkPlayableAbility("can't play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Curious Pair", false);
checkPlayableAbility("can play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Treats to Share", true);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertAllCommandsUsed();
assertActionsCount(playerA, 1);
assertPermanentCount(playerA, "Curious Pair", 0); assertPermanentCount(playerA, "Curious Pair", 0);
assertLibraryCount(playerA, 1); assertLibraryCount(playerA, 1);
} }
@ -477,19 +486,21 @@ public class AdventureCardsTest extends CardTestPlayerBase {
@Test @Test
public void testCantCastTreatsToShareWithGarruksHorde() { public void testCantCastTreatsToShareWithGarruksHorde() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Garruk's Horde");
addCard(Zone.BATTLEFIELD, playerA, "Forest");
removeAllCardsFromLibrary(playerA); removeAllCardsFromLibrary(playerA);
addCard(Zone.BATTLEFIELD, playerA, "Garruk's Horde");
//
addCard(Zone.LIBRARY, playerA, "Curious Pair"); addCard(Zone.LIBRARY, playerA, "Curious Pair");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
// showAvaileableAbilities("abils", 1, PhaseStep.PRECOMBAT_MAIN, playerA); checkPlayableAbility("can play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Curious Pair", true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Treats to Share"); checkPlayableAbility("can't play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Treats to Share", false);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertAllCommandsUsed();
assertActionsCount(playerA, 1);
assertPermanentCount(playerA, "Food", 0); assertPermanentCount(playerA, "Food", 0);
assertLibraryCount(playerA, 1); assertLibraryCount(playerA, 1);
} }

View file

@ -42,6 +42,7 @@ import mage.game.match.Match;
import mage.game.match.MatchPlayer; import mage.game.match.MatchPlayer;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken; import mage.game.permanent.PermanentToken;
import mage.game.stack.Spell;
import mage.game.stack.StackObject; import mage.game.stack.StackObject;
import mage.game.tournament.Tournament; import mage.game.tournament.Tournament;
import mage.player.ai.ComputerPlayer; import mage.player.ai.ComputerPlayer;
@ -430,6 +431,8 @@ public class TestPlayer implements Player {
// two search mode: for cards/permanents (strict) and for abilities (like) // two search mode: for cards/permanents (strict) and for abilities (like)
if (object instanceof Ability) { if (object instanceof Ability) {
return object.getName().startsWith(nameOrAlias); return object.getName().startsWith(nameOrAlias);
} else if (object instanceof Spell) {
return ((Spell) object).getSpellAbility().getName().startsWith(nameOrAlias);
} else { } else {
return object.getName().equals(nameOrAlias); return object.getName().equals(nameOrAlias);
} }
@ -668,11 +671,13 @@ public class TestPlayer implements Player {
} }
} else if (action.getAction().startsWith("waitStackResolved")) { } else if (action.getAction().startsWith("waitStackResolved")) {
if (game.getStack().isEmpty()) { if (game.getStack().isEmpty()) {
// can use next command // all done, can use next command
actions.remove(action); actions.remove(action);
continue;
} else { } else {
// need pass to empty stack // need to wait (don't remove command)
break; tryToPlayPriority(game);
return true;
} }
} else if (action.getAction().startsWith("playerAction:")) { } else if (action.getAction().startsWith("playerAction:")) {
String command = action.getAction(); String command = action.getAction();
@ -692,6 +697,7 @@ public class TestPlayer implements Player {
game.concede(getId()); game.concede(getId());
((GameImpl) game).checkConcede(); ((GameImpl) game).checkConcede();
actions.remove(action); actions.remove(action);
return true;
} }
} }
} else if (action.getAction().startsWith(AI_PREFIX)) { } else if (action.getAction().startsWith(AI_PREFIX)) {
@ -786,6 +792,13 @@ public class TestPlayer implements Player {
wasProccessed = true; wasProccessed = true;
} }
// check graveyard count: card name, count
if (params[0].equals(CHECK_COMMAND_GRAVEYARD_COUNT) && params.length == 3) {
assertGraveyardCount(action, game, computerPlayer, params[1], Integer.parseInt(params[2]));
actions.remove(action);
wasProccessed = true;
}
// check hand count: count // check hand count: count
if (params[0].equals(CHECK_COMMAND_HAND_COUNT) && params.length == 2) { if (params[0].equals(CHECK_COMMAND_HAND_COUNT) && params.length == 2) {
assertHandCount(action, game, computerPlayer, Integer.parseInt(params[1])); assertHandCount(action, game, computerPlayer, Integer.parseInt(params[1]));
@ -842,7 +855,9 @@ public class TestPlayer implements Player {
wasProccessed = true; wasProccessed = true;
} }
} }
if (!wasProccessed) { if (wasProccessed) {
return true;
} else {
Assert.fail("Unknow check command or params: " + command); Assert.fail("Unknow check command or params: " + command);
} }
} else if (action.getAction().startsWith(SHOW_PREFIX)) { } else if (action.getAction().startsWith(SHOW_PREFIX)) {
@ -938,17 +953,23 @@ public class TestPlayer implements Player {
} }
} }
if (!wasProccessed) { if (wasProccessed) {
return true;
} else {
Assert.fail("Unknow show command or params: " + command); Assert.fail("Unknow show command or params: " + command);
} }
} }
// you don't need to use stack command all the time, so some cast commands can be skiped to next check
if (game.getStack().isEmpty()) {
this.chooseStrictModeFailed("cast/activate", game,
"Can't find available command - " + action.getAction() + " (use checkPlayableAbility for non castable checks)", true);
} }
} // turn/step
} }
if (AIPlayer) {
computerPlayer.priority(game); tryToPlayPriority(game);
} else {
computerPlayer.pass(game);
}
// check to prevent endless loops // check to prevent endless loops
if (numberOfActions == actions.size()) { if (numberOfActions == actions.size()) {
foundNoAction++; foundNoAction++;
@ -962,6 +983,14 @@ public class TestPlayer implements Player {
return false; return false;
} }
private void tryToPlayPriority(Game game) {
if (AIPlayer) {
computerPlayer.priority(game);
} else {
computerPlayer.pass(game);
}
}
private Permanent findPermanentWithAssert(PlayerAction action, Game game, Player player, String cardName) { private Permanent findPermanentWithAssert(PlayerAction action, Game game, Player player, String cardName) {
for (Permanent perm : game.getBattlefield().getAllPermanents()) { for (Permanent perm : game.getBattlefield().getAllPermanents()) {
// need by controller // need by controller
@ -1208,6 +1237,17 @@ public class TestPlayer implements Player {
Assert.assertEquals(action.getActionName() + " - card " + permanentName + " must exists in exile zone with " + count + " instances", count, foundedCount); Assert.assertEquals(action.getActionName() + " - card " + permanentName + " must exists in exile zone with " + count + " instances", count, foundedCount);
} }
private void assertGraveyardCount(PlayerAction action, Game game, Player player, String permanentName, int count) {
int foundedCount = 0;
for (Card card : player.getGraveyard().getCards(game)) {
if (isObjectHaveTargetNameOrAlias(card, permanentName) && card.isOwnedBy(player.getId())) {
foundedCount++;
}
}
Assert.assertEquals(action.getActionName() + " - card " + permanentName + " must exists in graveyard zone with " + count + " instances", count, foundedCount);
}
private void assertHandCount(PlayerAction action, Game game, Player player, int count) { private void assertHandCount(PlayerAction action, Game game, Player player, int count) {
Assert.assertEquals(action.getActionName() + " - hand must contain " + count, count, player.getHand().size()); Assert.assertEquals(action.getActionName() + " - hand must contain " + count, count, player.getHand().size());
} }
@ -1668,7 +1708,16 @@ public class TestPlayer implements Player {
} }
private void chooseStrictModeFailed(String choiceType, Game game, String reason) { private void chooseStrictModeFailed(String choiceType, Game game, String reason) {
chooseStrictModeFailed(choiceType, game, reason, false);
}
private void chooseStrictModeFailed(String choiceType, Game game, String reason, boolean printAbilities) {
if (strictChooseMode && !AICanChooseInStrictMode) { if (strictChooseMode && !AICanChooseInStrictMode) {
if (printAbilities) {
printStart("Available abilities for " + computerPlayer.getName());
printAbilities(game, computerPlayer.getPlayable(game, true));
printEnd();
}
Assert.fail("Missing " + choiceType + " def for" Assert.fail("Missing " + choiceType + " def for"
+ " turn " + game.getTurnNum() + " turn " + game.getTurnNum()
+ ", step " + (game.getStep() != null ? game.getStep().getType().name() : "not started") + ", step " + (game.getStep() != null ? game.getStep().getType().name() : "not started")

View file

@ -93,6 +93,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
public static final String CHECK_COMMAND_PERMANENT_COUNT = "PERMANENT_COUNT"; public static final String CHECK_COMMAND_PERMANENT_COUNT = "PERMANENT_COUNT";
public static final String CHECK_COMMAND_PERMANENT_COUNTERS = "PERMANENT_COUNTERS"; public static final String CHECK_COMMAND_PERMANENT_COUNTERS = "PERMANENT_COUNTERS";
public static final String CHECK_COMMAND_EXILE_COUNT = "EXILE_COUNT"; public static final String CHECK_COMMAND_EXILE_COUNT = "EXILE_COUNT";
public static final String CHECK_COMMAND_GRAVEYARD_COUNT = "GRAVEYARD_COUNT";
public static final String CHECK_COMMAND_HAND_COUNT = "HAND_COUNT"; public static final String CHECK_COMMAND_HAND_COUNT = "HAND_COUNT";
public static final String CHECK_COMMAND_HAND_CARD_COUNT = "HAND_CARD_COUNT"; public static final String CHECK_COMMAND_HAND_CARD_COUNT = "HAND_CARD_COUNT";
public static final String CHECK_COMMAND_COMMAND_CARD_COUNT = "COMMAND_CARD_COUNT"; public static final String CHECK_COMMAND_COMMAND_CARD_COUNT = "COMMAND_CARD_COUNT";
@ -380,6 +381,11 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
check(checkName, turnNum, step, player, CHECK_COMMAND_EXILE_COUNT, permanentName, count.toString()); check(checkName, turnNum, step, player, CHECK_COMMAND_EXILE_COUNT, permanentName, count.toString());
} }
public void checkGraveyardCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer count) {
//Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_GRAVEYARD_COUNT, permanentName, count.toString());
}
public void checkHandCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, Integer count) { public void checkHandCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, Integer count) {
check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_COUNT, count.toString()); check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_COUNT, count.toString());
} }

View file

@ -145,9 +145,13 @@ public class SpellAbility extends ActivatedAbilityImpl {
this.costs.clearPaid(); this.costs.clearPaid();
} }
public String getName() {
return this.name;
}
@Override @Override
public String toString() { public String toString() {
return this.name; return getName();
} }
@Override @Override