From 28ac95cb100d8a26e711920735046f53648e0677 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Thu, 29 Nov 2018 19:11:20 +0400 Subject: [PATCH] Test framework: added new real time commands to prints info and checks: * show player's library, hand, battlefield, graveyard (use showXXX); * show exile zone, available abilities to activate (use showXXX); * checks targets, choices and commands in queue (use assert). --- .../java/org/mage/test/player/TestPlayer.java | 185 ++++++++++++++++-- .../base/impl/CardTestPlayerAPIImpl.java | 80 +++++++- 2 files changed, 243 insertions(+), 22 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index c6939d329e3..47f703ec0ec 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -54,6 +54,7 @@ import java.io.Serializable; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*; @@ -116,6 +117,10 @@ public class TestPlayer implements Player { return this.choices; } + public List getTargets() { + return this.targets; + } + public void addModeChoice(String mode) { modesSet.add(mode); } @@ -445,6 +450,8 @@ public class TestPlayer implements Player { groupsForTargetHandling = null; } } + // TODO: fix wrong commands (on non existing card), it's HUGE (350+ failed tests with wrong commands) + //Assert.fail("Can't find ability to activate command: " + command); } else if (action.getAction().startsWith("manaActivate:")) { String command = action.getAction(); command = command.substring(command.indexOf("manaActivate:") + 13); @@ -525,78 +532,143 @@ public class TestPlayer implements Player { } } else if (action.getAction().startsWith("check:")) { String command = action.getAction(); - command = command.substring(command.indexOf("check:") + 6); + command = command.substring(command.indexOf("check:") + "check:".length()); String[] params = command.split("@"); - boolean checkProccessed = false; + boolean wasProccessed = false; if (params.length > 0) { // check PT: card name, P, T if (params[0].equals(CHECK_COMMAND_PT) && params.length == 4) { assertPT(action, game, computerPlayer, params[1], Integer.parseInt(params[2]), Integer.parseInt(params[3])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; } // check life: life if (params[0].equals(CHECK_COMMAND_LIFE) && params.length == 2) { assertLife(action, game, computerPlayer, Integer.parseInt(params[1])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; } // check ability: card name, ability class, must have if (params[0].equals(CHECK_COMMAND_ABILITY) && params.length == 4) { assertAbility(action, game, computerPlayer, params[1], params[2], Boolean.parseBoolean(params[3])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; } // check battlefield count: card name, count if (params[0].equals(CHECK_COMMAND_PERMANENT_COUNT) && params.length == 3) { assertPermanentCount(action, game, computerPlayer, params[1], Integer.parseInt(params[2])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; } // check exile count: card name, count if (params[0].equals(CHECK_COMMAND_EXILE_COUNT) && params.length == 3) { assertExileCount(action, game, computerPlayer, params[1], Integer.parseInt(params[2])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; } // check hand count: count if (params[0].equals(CHECK_COMMAND_HAND_COUNT) && params.length == 2) { assertHandCount(action, game, computerPlayer, Integer.parseInt(params[1])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; } // check color: card name, colors, must have if (params[0].equals(CHECK_COMMAND_COLOR) && params.length == 4) { assertColor(action, game, computerPlayer, params[1], params[2], Boolean.parseBoolean(params[3])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; } // check subtype: card name, subtype, must have if (params[0].equals(CHECK_COMMAND_SUBTYPE) && params.length == 4) { assertSubType(action, game, computerPlayer, params[1], SubType.fromString(params[2]), Boolean.parseBoolean(params[3])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; } // check mana pool: colors, amount if (params[0].equals(CHECK_COMMAND_MANA_POOL) && params.length == 3) { assertManaPool(action, game, computerPlayer, params[1], Integer.parseInt(params[2])); actions.remove(action); - checkProccessed = true; + wasProccessed = true; + } + } + if (!wasProccessed) { + Assert.fail("Unknow check command or params: " + command); + } + } else if (action.getAction().startsWith("show:")) { + String command = action.getAction(); + command = command.substring(command.indexOf("show:") + "show:".length()); + + String[] params = command.split("@"); + boolean wasProccessed = false; + if (params.length > 0) { + + // show library + if (params[0].equals(SHOW_COMMAND_LIBRARY) && params.length == 1) { + printStart(action.getActionName()); + printCards(computerPlayer.getLibrary().getCards(game)); + printEnd(); + actions.remove(action); + wasProccessed = true; + } + + // show hand + if (params[0].equals(SHOW_COMMAND_HAND) && params.length == 1) { + printStart(action.getActionName()); + printCards(computerPlayer.getHand().getCards(game)); + printEnd(); + actions.remove(action); + wasProccessed = true; + } + + // show battlefield + if (params[0].equals(SHOW_COMMAND_BATTLEFIELD) && params.length == 1) { + printStart(action.getActionName()); + printPermanents(game.getBattlefield().getAllActivePermanents(computerPlayer.getId())); + printEnd(); + actions.remove(action); + wasProccessed = true; + } + + // show graveyard + if (params[0].equals(SHOW_COMMAND_GRAVEYEARD) && params.length == 1) { + printStart(action.getActionName()); + printCards(computerPlayer.getGraveyard().getCards(game)); + printEnd(); + actions.remove(action); + wasProccessed = true; + } + + // show exile + if (params[0].equals(SHOW_COMMAND_EXILE) && params.length == 1) { + printStart(action.getActionName()); + printCards(game.getExile().getAllCards(game)); + printEnd(); + actions.remove(action); + wasProccessed = true; + } + + // show available abilities + if (params[0].equals(SHOW_COMMAND_AVAILABLE_ABILITIES) && params.length == 1) { + printStart(action.getActionName()); + printAbilities(game, computerPlayer.getPlayable(game, true)); + printEnd(); + actions.remove(action); + wasProccessed = true; } } - if (!checkProccessed) { - Assert.fail("Unknow check command or params: " + command); + if (!wasProccessed) { + Assert.fail("Unknow show command or params: " + command); } } } @@ -629,6 +701,73 @@ public class TestPlayer implements Player { return null; } + private void printStart(String name) { + System.out.println("\n" + name + ":"); + } + + private void printEnd() { + System.out.println(); + } + + private void printCards(Set cards) { + printCards(cards.stream().collect(Collectors.toList())); + } + + private void printCards(List cards) { + System.out.println("Total cards: " + cards.size()); + + List data = cards.stream() + .map(Card::getIdName) + .sorted() + .collect(Collectors.toList()); + + for (String s : data) { + System.out.println(s); + } + } + + private void printPermanents(List cards) { + System.out.println("Total permanents: " + cards.size()); + + List data = cards.stream() + .map(c -> (c.getIdName() + + " - " + c.getPower().getValue() + + "/" + c.getToughness().getValue() + + ", " + (c.isTapped() ? "Tapped" : "Untapped") + )) + .sorted() + .collect(Collectors.toList()); + + for (String s : data) { + System.out.println(s); + } + } + + private void printAbilities(Game game, List abilities) { + + + System.out.println("Total abilities: " + (abilities != null ? abilities.size() : 0)); + if (abilities == null) { + return; + } + + List data = abilities.stream() + .map(a -> ( + a.getZone() + " -> " + + a.getSourceObject(game).getIdName() + " -> " + + (a.getRule().length() > 0 + ? a.getRule().substring(0, Math.min(20, a.getRule().length()) - 1) + : a.getClass().getSimpleName()) + + "..." + )) + .sorted() + .collect(Collectors.toList()); + + for (String s : data) { + System.out.println(s); + } + } + private void assertPT(PlayerAction action, Game game, Player player, String permanentName, int Power, int Toughness) { Permanent perm = findPermanentWithAssert(action, game, player, permanentName); @@ -976,6 +1115,8 @@ public class TestPlayer implements Player { if (choice.setChoiceByAnswers(choices, true)) { return true; } + // TODO: enable fail checks and fix tests + //Assert.fail("Wrong choice"); } return computerPlayer.choose(outcome, choice, game); } @@ -991,6 +1132,8 @@ public class TestPlayer implements Player { } } } + // TODO: enable fail checks and fix tests + //Assert.fail("wrong choice"); } return computerPlayer.chooseReplacementEffect(rEffects, game); } @@ -1135,6 +1278,13 @@ public class TestPlayer implements Player { } } } + + // TODO: enable fail checks and fix tests + /* + if (!target.getTargetName().equals("starting player")) { + Assert.fail("Wrong choice"); + } + */ } return computerPlayer.choose(outcome, target, sourceId, game, options); @@ -1451,6 +1601,9 @@ public class TestPlayer implements Player { return true; } } + + // TODO: enable fail checks and fix tests + //Assert.fail("Wrong target"); } return computerPlayer.chooseTarget(outcome, cards, target, source, game); } @@ -1464,6 +1617,8 @@ public class TestPlayer implements Player { return ability; } } + // TODO: enable fail checks and fix tests + //Assert.fail("Wrong choice"); } return computerPlayer.chooseTriggeredAbility(abilities, game); } @@ -1487,6 +1642,8 @@ public class TestPlayer implements Player { choices.remove(0); return true; } + // TODO: enable fail checks and fix tests + //Assert.fail("Wrong choice"); } return computerPlayer.chooseUse(outcome, message, secondMessage, trueText, falseText, source, game); } @@ -2643,6 +2800,8 @@ public class TestPlayer implements Player { return true; } } + // TODO: enable fail checks and fix tests + //Assert.fail("Wrong choice"); } return computerPlayer.choose(outcome, cards, target, game); } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index b858d8609b5..016f1d37fbc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -26,6 +26,7 @@ import mage.players.ManaPool; import mage.players.Player; import org.junit.Assert; import org.junit.Before; +import org.mage.test.player.PlayerAction; import org.mage.test.player.TestPlayer; import org.mage.test.serverside.base.CardTestAPI; import org.mage.test.serverside.base.MageTestPlayerBase; @@ -48,6 +49,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement // Defines the constant if for activate ability is not target but a ability on the stack to define public static final String NO_TARGET = "NO_TARGET"; + // TODO: add target player param to commands public static final String CHECK_COMMAND_PT = "PT"; public static final String CHECK_COMMAND_LIFE = "LIFE"; public static final String CHECK_COMMAND_ABILITY = "ABILITY"; @@ -58,6 +60,14 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement public static final String CHECK_COMMAND_SUBTYPE = "SUBTYPE"; public static final String CHECK_COMMAND_MANA_POOL = "MANA_POOL"; + // TODO: add target player param to commands + public static final String SHOW_COMMAND_LIBRARY = "LIBRARY"; + public static final String SHOW_COMMAND_HAND = "HAND"; + public static final String SHOW_COMMAND_BATTLEFIELD = "BATTLEFIELD"; + public static final String SHOW_COMMAND_GRAVEYEARD = "GRAVEYARD"; + public static final String SHOW_COMMAND_EXILE = "EXILE"; + public static final String SHOW_COMMAND_AVAILABLE_ABILITIES = "AVAILABLE_ABILITIES"; + protected GameOptions gameOptions; protected String deckNameA; @@ -238,6 +248,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement return player; } + // check commands + private void check(String checkName, int turnNum, PhaseStep step, TestPlayer player, String command, String... params) { String res = "check:" + command; for (String param : params) { @@ -282,6 +294,40 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement check(checkName, turnNum, step, player, CHECK_COMMAND_MANA_POOL, colors, amount.toString()); } + // show commands + + private void show(String showName, int turnNum, PhaseStep step, TestPlayer player, String command, String... params) { + String res = "show:" + command; + for (String param : params) { + res += "@" + param; + } + player.addAction(showName, turnNum, step, res); + } + + public void showLibrary(String showName, int turnNum, PhaseStep step, TestPlayer player) { + show(showName, turnNum, step, player, SHOW_COMMAND_LIBRARY); + } + + public void showHand(String showName, int turnNum, PhaseStep step, TestPlayer player) { + show(showName, turnNum, step, player, SHOW_COMMAND_HAND); + } + + public void showBattlefield(String showName, int turnNum, PhaseStep step, TestPlayer player) { + show(showName, turnNum, step, player, SHOW_COMMAND_BATTLEFIELD); + } + + public void showGraveyard(String showName, int turnNum, PhaseStep step, TestPlayer player) { + show(showName, turnNum, step, player, SHOW_COMMAND_GRAVEYEARD); + } + + public void showExile(String showName, int turnNum, PhaseStep step, TestPlayer player) { + show(showName, turnNum, step, player, SHOW_COMMAND_EXILE); + } + + public void showAvaileableAbilities(String showName, int turnNum, PhaseStep step, TestPlayer player) { + show(showName, turnNum, step, player, SHOW_COMMAND_AVAILABLE_ABILITIES); + } + /** * Removes all cards from player's library from the game. Usually this * should be used once before initialization to form the library in certain @@ -1080,15 +1126,27 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement Assert.assertEquals("(Library " + player.getName() + ") Card counts are not equal (" + cardName + ')', count, actualCount); } - /** - * Asserts added actions count. Useful to make sure that all actions were - * executed. - * - * @param player - * @param count - */ - public void assertActionCount(TestPlayer player, int count) { - Assert.assertEquals("Actions left are not equal: ", count, player.getActionCount()); + public void assertActionsCount(TestPlayer player, int count) throws AssertionError { + Assert.assertEquals("(Actions " + player.getName() + ") Count are not equel (founded [" + + player.getActions().stream().map(PlayerAction::getAction).collect(Collectors.joining(", ")) + + "])", count, player.getActions().size()); + } + + public void assertChoicesCount(TestPlayer player, int count) throws AssertionError { + Assert.assertEquals("(Choices " + player.getName() + ") Count are not equel (founded " + player.getChoices() + ")", count, player.getChoices().size()); + } + + public void assertTargetsCount(TestPlayer player, int count) throws AssertionError { + Assert.assertEquals("(Targets " + player.getName() + ") Count are not equel (founded " + player.getTargets() + ")", count, player.getTargets().size()); + } + + public void assertAllCommandsUsed() throws AssertionError { + for(Player player : currentGame.getPlayers().values()) { + TestPlayer testPlayer = (TestPlayer) player; + assertActionsCount(testPlayer, 0); + assertChoicesCount(testPlayer, 0); + assertTargetsCount(testPlayer, 0); + } } public void assertActivePlayer(TestPlayer player) { @@ -1243,18 +1301,22 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement } public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability) { + // TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't player.addAction(turnNum, step, "activate:" + ability); } public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, Player target) { + // TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't player.addAction(turnNum, step, "activate:" + ability + "$targetPlayer=" + target.getName()); } public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String... targetNames) { + // TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't player.addAction(turnNum, step, "activate:" + ability + "$target=" + String.join("^", targetNames)); } public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String targetName, String spellOnStack) { + // TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't this.activateAbility(turnNum, step, player, ability, targetName, spellOnStack, StackClause.WHILE_ON_STACK); }