mirror of
https://github.com/magefree/mage.git
synced 2025-12-23 12:02:01 -08:00
Test framework: added commands for real time checks/assertions:
* new checks: color, subtype, ability, PT, permanent and hand count; * more info in #4936;
This commit is contained in:
parent
f30c0a7054
commit
4851ba9e84
5 changed files with 344 additions and 106 deletions
|
|
@ -31,16 +31,17 @@ package org.mage.test.player;
|
|||
import mage.constants.PhaseStep;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class PlayerAction {
|
||||
|
||||
private final String actionName;
|
||||
private final int turnNum;
|
||||
private final PhaseStep step;
|
||||
private final String action;
|
||||
|
||||
public PlayerAction(int turnNum, PhaseStep step, String action) {
|
||||
public PlayerAction(String actionName, int turnNum, PhaseStep step, String action) {
|
||||
this.actionName = actionName;
|
||||
this.turnNum = turnNum;
|
||||
this.step = step;
|
||||
this.action = action;
|
||||
|
|
@ -58,4 +59,7 @@ public class PlayerAction {
|
|||
return action;
|
||||
}
|
||||
|
||||
public String getActionName() {
|
||||
return this.actionName;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,11 @@ import java.io.Serializable;
|
|||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.operations.Bool;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.Cost;
|
||||
|
|
@ -76,11 +79,15 @@ import mage.players.Player;
|
|||
import mage.players.net.UserData;
|
||||
import mage.target.*;
|
||||
import mage.target.common.*;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @author Simown
|
||||
* @author JayDi85
|
||||
*/
|
||||
@Ignore
|
||||
public class TestPlayer implements Player {
|
||||
|
|
@ -136,7 +143,11 @@ public class TestPlayer implements Player {
|
|||
}
|
||||
|
||||
public void addAction(int turnNum, PhaseStep step, String action) {
|
||||
actions.add(new PlayerAction(turnNum, step, action));
|
||||
actions.add(new PlayerAction("", turnNum, step, action));
|
||||
}
|
||||
|
||||
public void addAction(String actionName, int turnNum, PhaseStep step, String action) {
|
||||
actions.add(new PlayerAction(actionName, turnNum, step, action));
|
||||
}
|
||||
|
||||
public List<PlayerAction> getActions() {
|
||||
|
|
@ -162,27 +173,27 @@ public class TestPlayer implements Player {
|
|||
/**
|
||||
* Finds a permanent based on a general filter an their name and possible
|
||||
* index.
|
||||
*
|
||||
* <p>
|
||||
* An index is permitted after the permanent's name to denote their index on
|
||||
* the battlefield Either use name="<permanent>" which will get the first
|
||||
* permanent with that name on the battlefield that meets the filter
|
||||
* criteria or name="<permanent>:<index>" to get the named permanent with
|
||||
* that index on the battlefield.
|
||||
*
|
||||
* <p>
|
||||
* Permanents are zero indexed in the order they entered the battlefield for
|
||||
* each controller:
|
||||
*
|
||||
* <p>
|
||||
* findPermanent(new AttackingCreatureFilter(), "Human", <controllerID>,
|
||||
* <game>) Will find the first "Human" creature that entered the battlefield
|
||||
* under this controller and is attacking.
|
||||
*
|
||||
* <p>
|
||||
* findPermanent(new FilterControllerPermanent(), "Fabled Hero:3",
|
||||
* <controllerID>, <game>) Will find the 4th permanent named "Fabled Hero"
|
||||
* that entered the battlefield under this controller
|
||||
*
|
||||
* <p>
|
||||
* An exception will be thrown if no permanents match the criteria or the
|
||||
* index is larger than the number of permanents found with that name.
|
||||
*
|
||||
* <p>
|
||||
* failOnNotFound boolean controls if this function returns null for a
|
||||
* permanent not found on the battlefield. Currently used only as a
|
||||
* workaround for attackers in selectAttackers() being able to attack
|
||||
|
|
@ -431,7 +442,7 @@ public class TestPlayer implements Player {
|
|||
if (groups.length > 2 && !checkExecuteCondition(groups, game)) {
|
||||
break;
|
||||
}
|
||||
for (Ability ability : computerPlayer.getPlayable(game, true)) {
|
||||
for (Ability ability : computerPlayer.getPlayable(game, true)) { // add wrong action log?
|
||||
if (ability.toString().startsWith(groups[0])) {
|
||||
int bookmark = game.bookmarkState();
|
||||
Ability newAbility = ability.copy();
|
||||
|
|
@ -526,6 +537,60 @@ public class TestPlayer implements Player {
|
|||
actions.remove(action);
|
||||
}
|
||||
}
|
||||
} else if (action.getAction().startsWith("check:")) {
|
||||
String command = action.getAction();
|
||||
command = command.substring(command.indexOf("check:") + 6);
|
||||
|
||||
String[] params = command.split("@");
|
||||
boolean checkProccessed = 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkProccessed) {
|
||||
Assert.fail("Unknow check command or params: " + command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -546,6 +611,103 @@ public class TestPlayer implements Player {
|
|||
return false;
|
||||
}
|
||||
|
||||
private Permanent findPermanentWithAssert(PlayerAction action, Game game, Player player, String cardName) {
|
||||
Permanent founded = null;
|
||||
for (Permanent perm : game.getBattlefield().getAllPermanents()) {
|
||||
if (perm.getName().equals(cardName) && perm.getControllerId().equals(player.getId())) {
|
||||
return perm;
|
||||
}
|
||||
}
|
||||
Assert.assertNotNull(action.getActionName() + " - can''t find permanent to check PT: " + cardName, founded);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void assertPT(PlayerAction action, Game game, Player player, String permanentName, int Power, int Toughness) {
|
||||
Permanent perm = findPermanentWithAssert(action, game, player, permanentName);
|
||||
|
||||
Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " have wrong power: " + perm.getPower().getValue() + " <> " + Power,
|
||||
Power, perm.getPower().getValue());
|
||||
Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " have wrong toughness: " + perm.getToughness().getValue() + " <> " + Toughness,
|
||||
Toughness, perm.getToughness().getValue());
|
||||
}
|
||||
|
||||
private void assertAbility(PlayerAction action, Game game, Player player, String permanentName, String abilityClass, boolean mustHave) {
|
||||
Permanent perm = findPermanentWithAssert(action, game, player, permanentName);
|
||||
|
||||
boolean founded = false;
|
||||
for (Ability ability : perm.getAbilities(game)) {
|
||||
if (ability.getClass().getName().equals(abilityClass)) {
|
||||
founded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mustHave) {
|
||||
Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " must have ability " + abilityClass, true, founded);
|
||||
} else {
|
||||
Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " must have not ability " + abilityClass, false, founded);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertPermanentCount(PlayerAction action, Game game, Player player, String permanentName, int count) {
|
||||
int foundedCount = 0;
|
||||
for (Permanent perm : game.getBattlefield().getAllPermanents()) {
|
||||
if (perm.getName().equals(permanentName) && perm.getControllerId().equals(player.getId())) {
|
||||
foundedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " must exists in " + count + " instances", count, foundedCount);
|
||||
}
|
||||
|
||||
private void assertHandCount(PlayerAction action, Game game, Player player, int count) {
|
||||
Assert.assertEquals(action.getActionName() + " - hand must contain " + count, count, player.getHand().size());
|
||||
}
|
||||
|
||||
private void assertColor(PlayerAction action, Game game, Player player, String permanentName, String colors, boolean mustHave) {
|
||||
Assert.assertNotEquals(action.getActionName() + " - must setup colors", "", colors);
|
||||
|
||||
Permanent card = findPermanentWithAssert(action, game, player, permanentName);
|
||||
ObjectColor cardColor = card.getColor(game);
|
||||
ObjectColor searchColors = new ObjectColor(colors);
|
||||
|
||||
List<ObjectColor> colorsHave = new ArrayList<>();
|
||||
List<ObjectColor> colorsDontHave = new ArrayList<>();
|
||||
|
||||
for (ObjectColor searchColor : searchColors.getColors()) {
|
||||
if (cardColor.shares(searchColor)) {
|
||||
colorsHave.add(searchColor);
|
||||
} else {
|
||||
colorsDontHave.add(searchColor);
|
||||
}
|
||||
}
|
||||
|
||||
if (mustHave) {
|
||||
Assert.assertEquals(action.getActionName() + " - must contain colors [" + searchColors.toString() + "] but found only [" + cardColor.toString() + "]", 0, colorsDontHave.size());
|
||||
} else {
|
||||
Assert.assertEquals(action.getActionName() + " - must not contain colors [" + searchColors.toString() + "] but found [" + cardColor.toString() + "]", 0, colorsHave.size());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertSubType(PlayerAction action, Game game, Player player, String permanentName, SubType subType, boolean mustHave) {
|
||||
|
||||
Permanent perm = findPermanentWithAssert(action, game, player, permanentName);
|
||||
|
||||
boolean founded = false;
|
||||
for (SubType st : perm.getSubtype(game)) {
|
||||
if (st.equals(subType)) {
|
||||
founded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mustHave) {
|
||||
Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " must have subtype " + subType, true, founded);
|
||||
} else {
|
||||
Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " must have not subtype " + subType, false, founded);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterates through each player on the current turn and asserts if they can attack or block legally this turn
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.mage.test.serverside.base.impl;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -47,6 +48,13 @@ 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";
|
||||
|
||||
public static final String CHECK_COMMAND_PT = "PT";
|
||||
public static final String CHECK_COMMAND_ABILITY = "ABILITY";
|
||||
public static final String CHECK_COMMAND_PERMANENT_COUNT = "PERMANENT_COUNT";
|
||||
public static final String CHECK_COMMAND_HAND_COUNT = "HAND_COUNT";
|
||||
public static final String CHECK_COMMAND_COLOR = "COLOR";
|
||||
public static final String CHECK_COMMAND_SUBTYPE = "SUBTYPE";
|
||||
|
||||
protected GameOptions gameOptions;
|
||||
|
||||
protected String deckNameA;
|
||||
|
|
@ -219,6 +227,38 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
return player;
|
||||
}
|
||||
|
||||
private void check(String checkName, int turnNum, PhaseStep step, TestPlayer player, String command, String... params) {
|
||||
String res = "check:" + command;
|
||||
for (String param : params) {
|
||||
res += "@" + param;
|
||||
}
|
||||
player.addAction(checkName, turnNum, step, res);
|
||||
}
|
||||
|
||||
public void checkPT(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer power, Integer toughness) {
|
||||
check(checkName, turnNum, step, player, CHECK_COMMAND_PT, permanentName, power.toString(), toughness.toString());
|
||||
}
|
||||
|
||||
public void checkAbility(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Class<?> abilityClass, Boolean mustHave) {
|
||||
check(checkName, turnNum, step, player, CHECK_COMMAND_ABILITY, permanentName, abilityClass.getName(), mustHave.toString());
|
||||
}
|
||||
|
||||
public void checkPermanentCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer count) {
|
||||
check(checkName, turnNum, step, player, CHECK_COMMAND_PERMANENT_COUNT, permanentName, count.toString());
|
||||
}
|
||||
|
||||
public void checkHandCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, Integer count) {
|
||||
check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_COUNT, count.toString());
|
||||
}
|
||||
|
||||
public void checkColor(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, String colors, Boolean mustHave) {
|
||||
check(checkName, turnNum, step, player, CHECK_COMMAND_COLOR, permanentName, colors, mustHave.toString());
|
||||
}
|
||||
|
||||
public void checkSubType(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, SubType subType, Boolean mustHave) {
|
||||
check(checkName, turnNum, step, player, CHECK_COMMAND_SUBTYPE, permanentName, subType.toString(), mustHave.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all cards from player's library from the game. Usually this
|
||||
* should be used once before initialization to form the library in certain
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import java.util.regex.Pattern;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class VerifyCardDataTest {
|
||||
|
|
@ -39,9 +38,18 @@ public class VerifyCardDataTest {
|
|||
private static final boolean CHECK_SOURCE_TOKENS = false;
|
||||
|
||||
private static final HashMap<String, Set<String>> skipCheckLists = new HashMap<>();
|
||||
private static void skipListCreate(String listName){ skipCheckLists.put(listName, new LinkedHashSet<>()); }
|
||||
private static void skipListAddName(String listName, String name){ skipCheckLists.get(listName).add(name); }
|
||||
private static boolean skipListHaveName(String listName, String name){ return skipCheckLists.get(listName).contains(name); }
|
||||
|
||||
private static void skipListCreate(String listName) {
|
||||
skipCheckLists.put(listName, new LinkedHashSet<>());
|
||||
}
|
||||
|
||||
private static void skipListAddName(String listName, String name) {
|
||||
skipCheckLists.get(listName).add(name);
|
||||
}
|
||||
|
||||
private static boolean skipListHaveName(String listName, String name) {
|
||||
return skipCheckLists.get(listName).contains(name);
|
||||
}
|
||||
|
||||
static {
|
||||
// skip lists for checks (example: unstable cards with same name may have different stats)
|
||||
|
|
@ -455,7 +463,9 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
|
||||
private void checkColors(Card card, JsonCard ref) {
|
||||
if (skipListHaveName("COLOR", card.getName())){ return; }
|
||||
if (skipListHaveName("COLOR", card.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<String> expected = ref.colors;
|
||||
ObjectColor color = card.getColor(null);
|
||||
|
|
@ -473,7 +483,9 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
|
||||
private void checkSubtypes(Card card, JsonCard ref) {
|
||||
if (skipListHaveName("SUBTYPE", card.getName())){ return; }
|
||||
if (skipListHaveName("SUBTYPE", card.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<String> expected = ref.subtypes;
|
||||
|
||||
|
|
@ -493,7 +505,9 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
|
||||
private void checkSupertypes(Card card, JsonCard ref) {
|
||||
if (skipListHaveName("SUPERTYPE", card.getName())){ return; }
|
||||
if (skipListHaveName("SUPERTYPE", card.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<String> expected = ref.supertypes;
|
||||
if (!eqSet(card.getSuperType().stream().map(s -> s.toString()).collect(Collectors.toList()), expected)) {
|
||||
|
|
@ -502,7 +516,9 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
|
||||
private void checkTypes(Card card, JsonCard ref) {
|
||||
if (skipListHaveName("TYPE", card.getName())){ return; }
|
||||
if (skipListHaveName("TYPE", card.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<String> expected = ref.types;
|
||||
List<String> type = new ArrayList<>();
|
||||
|
|
@ -522,7 +538,9 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
|
||||
private void checkPT(Card card, JsonCard ref) {
|
||||
if (skipListHaveName("PT", card.getName())){ return; }
|
||||
if (skipListHaveName("PT", card.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!eqPT(card.getPower().toString(), ref.power) || !eqPT(card.getToughness().toString(), ref.toughness)) {
|
||||
String pt = card.getPower() + "/" + card.getToughness();
|
||||
|
|
@ -540,7 +558,9 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
|
||||
private void checkCost(Card card, JsonCard ref) {
|
||||
if (skipListHaveName("COST", card.getName())){ return; }
|
||||
if (skipListHaveName("COST", card.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
String expected = ref.manaCost;
|
||||
String cost = join(card.getManaCost().getSymbols());
|
||||
|
|
@ -556,7 +576,9 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
|
||||
private void checkNumbers(Card card, JsonCard ref) {
|
||||
if (skipListHaveName("NUMBER", card.getName())){ return; }
|
||||
if (skipListHaveName("NUMBER", card.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
String expected = ref.number;
|
||||
String current = card.getCardNumber();
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import java.util.Arrays;
|
|||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import mage.util.SubTypeList;
|
||||
|
||||
public enum SubType {
|
||||
|
|
@ -328,7 +329,6 @@ public enum SubType {
|
|||
TROOPER("Trooper", SubTypeSet.CreatureType, true), // Star Wars
|
||||
TRILOBITE("Trilobite", SubTypeSet.CreatureType),
|
||||
TWILEK("Twi'lek", SubTypeSet.CreatureType, true), // Star Wars
|
||||
|
||||
// U
|
||||
UGNAUGHT("Ugnaught", SubTypeSet.CreatureType, true),
|
||||
UNICORN("Unicorn", SubTypeSet.CreatureType),
|
||||
|
|
@ -429,6 +429,16 @@ public enum SubType {
|
|||
return description;
|
||||
}
|
||||
|
||||
public static SubType fromString(String value) {
|
||||
for (SubType st : SubType.values()) {
|
||||
if (st.toString().equals(value)) {
|
||||
return st;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Can''t find subtype enum value: " + value);
|
||||
}
|
||||
|
||||
public static SubType byDescription(String subType) {
|
||||
for (SubType s : values()) {
|
||||
if (s.getDescription().equals(subType)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue