mirror of
https://github.com/correl/mage.git
synced 2024-11-15 11:09:30 +00:00
Enhanced test framework for multiplayer games
This commit is contained in:
parent
7b268c7fcb
commit
475666be4c
1 changed files with 298 additions and 0 deletions
|
@ -0,0 +1,298 @@
|
||||||
|
package org.mage.test.serverside.base;
|
||||||
|
|
||||||
|
import mage.Constants;
|
||||||
|
import mage.Constants.PhaseStep;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.decks.Deck;
|
||||||
|
import mage.cards.decks.importer.DeckImporterUtil;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import mage.game.*;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.mage.test.player.TestPlayer;
|
||||||
|
import org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for testing single cards and effects in multiplayer game.
|
||||||
|
* For PvP games {@see CardTestPlayerBase}
|
||||||
|
*
|
||||||
|
* @author magenoxx_at_gmail.com
|
||||||
|
*/
|
||||||
|
public abstract class CardTestMultiPlayerBase extends CardTestPlayerAPIImpl {
|
||||||
|
|
||||||
|
protected enum ExpectedType {
|
||||||
|
TURN_NUMBER,
|
||||||
|
RESULT,
|
||||||
|
LIFE,
|
||||||
|
BATTLEFIELD,
|
||||||
|
GRAVEYARD,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GameOptions gameOptions;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void reset() throws GameException, FileNotFoundException {
|
||||||
|
if (currentGame != null) {
|
||||||
|
logger.debug("Resetting previous game and creating new one!");
|
||||||
|
currentGame = null;
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
Game game = new FreeForAll(Constants.MultiplayerAttackOption.LEFT, Constants.RangeOfInfluence.ONE);
|
||||||
|
|
||||||
|
playerA = createPlayer(game, playerA, "PlayerA");
|
||||||
|
playerB = createPlayer(game, playerB, "PlayerB");
|
||||||
|
playerC = createPlayer(game, playerC, "PlayerC");
|
||||||
|
playerD = createPlayer(game, playerD, "PlayerD");
|
||||||
|
|
||||||
|
activePlayer = playerA;
|
||||||
|
currentGame = game;
|
||||||
|
|
||||||
|
stopOnTurn = 2;
|
||||||
|
stopAtStep = PhaseStep.UNTAP;
|
||||||
|
|
||||||
|
for (Player player : currentGame.getPlayers().values()) {
|
||||||
|
TestPlayer testPlayer = (TestPlayer)player;
|
||||||
|
getCommands(testPlayer).clear();
|
||||||
|
getLibraryCards(testPlayer).clear();
|
||||||
|
getHandCards(testPlayer).clear();
|
||||||
|
getBattlefieldCards(testPlayer).clear();
|
||||||
|
getGraveCards(testPlayer).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
gameOptions = new GameOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String path) throws FileNotFoundException, GameException {
|
||||||
|
String cardPath = TESTS_PATH + path;
|
||||||
|
File checkFile = new File(cardPath);
|
||||||
|
if (!checkFile.exists()) {
|
||||||
|
throw new FileNotFoundException("Couldn't find test file: " + cardPath);
|
||||||
|
}
|
||||||
|
if (checkFile.isDirectory()) {
|
||||||
|
throw new FileNotFoundException("Couldn't find test file: " + cardPath + ". It is directory.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentGame != null) {
|
||||||
|
logger.debug("Resetting previous game and creating new one!");
|
||||||
|
currentGame = null;
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
Game game = new TwoPlayerDuel(Constants.MultiplayerAttackOption.LEFT, Constants.RangeOfInfluence.ALL);
|
||||||
|
|
||||||
|
playerA = createNewPlayer("ComputerA");
|
||||||
|
playerA.setTestMode(true);
|
||||||
|
|
||||||
|
Deck deck = Deck.load(DeckImporterUtil.importDeck("RB Aggro.dck"));
|
||||||
|
|
||||||
|
if (deck.getCards().size() < 40) {
|
||||||
|
throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck.getCards().size());
|
||||||
|
}
|
||||||
|
game.addPlayer(playerA, deck);
|
||||||
|
game.loadCards(deck.getCards(), playerA.getId());
|
||||||
|
|
||||||
|
playerB = createNewPlayer("ComputerB");
|
||||||
|
playerB.setTestMode(true);
|
||||||
|
Deck deck2 = Deck.load(DeckImporterUtil.importDeck("RB Aggro.dck"));
|
||||||
|
if (deck2.getCards().size() < 40) {
|
||||||
|
throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck2.getCards().size());
|
||||||
|
}
|
||||||
|
game.addPlayer(playerB, deck2);
|
||||||
|
game.loadCards(deck2.getCards(), playerB.getId());
|
||||||
|
|
||||||
|
parseScenario(cardPath);
|
||||||
|
|
||||||
|
activePlayer = playerA;
|
||||||
|
currentGame = game;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts testing card by starting current game.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException In case game wasn't created previously. Use {@link #load} method to initialize the game.
|
||||||
|
*/
|
||||||
|
public void execute() throws IllegalStateException {
|
||||||
|
if (currentGame == null || activePlayer == null) {
|
||||||
|
throw new IllegalStateException("Game is not initialized. Use load method to load a test case and initialize a game.");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Player player : currentGame.getPlayers().values()) {
|
||||||
|
TestPlayer testPlayer = (TestPlayer)player;
|
||||||
|
currentGame.cheat(player.getId(), getCommands(testPlayer));
|
||||||
|
currentGame.cheat(player.getId(), getLibraryCards(testPlayer), getHandCards(testPlayer),
|
||||||
|
getBattlefieldCards(testPlayer), getGraveCards(testPlayer));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean testMode = true;
|
||||||
|
long t1 = System.nanoTime();
|
||||||
|
|
||||||
|
gameOptions.testMode = true;
|
||||||
|
gameOptions.stopOnTurn = stopOnTurn;
|
||||||
|
gameOptions.stopAtStep = stopAtStep;
|
||||||
|
currentGame.start(activePlayer.getId(), gameOptions);
|
||||||
|
long t2 = System.nanoTime();
|
||||||
|
logger.debug("Winner: " + currentGame.getWinner());
|
||||||
|
logger.info("Test has been executed. Execution time: " + (t2 - t1) / 1000000 + " ms");
|
||||||
|
|
||||||
|
assertTheResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert expected and actual results.
|
||||||
|
*/
|
||||||
|
private void assertTheResults() {
|
||||||
|
logger.debug("Matching expected results:");
|
||||||
|
for (String line : expectedResults) {
|
||||||
|
boolean ok = false;
|
||||||
|
try {
|
||||||
|
ExpectedType type = getExpectedType(line);
|
||||||
|
if (type.equals(CardTestMultiPlayerBase.ExpectedType.UNKNOWN)) {
|
||||||
|
throw new AssertionError("Unknown expected type, check the line in $expected section=" + line);
|
||||||
|
}
|
||||||
|
parseType(type, line);
|
||||||
|
ok = true;
|
||||||
|
} finally {
|
||||||
|
logger.info(" " + line + " - " + (ok ? "OK" : "ERROR"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExpectedType getExpectedType(String line) {
|
||||||
|
if (line.startsWith("turn:")) {
|
||||||
|
return CardTestMultiPlayerBase.ExpectedType.TURN_NUMBER;
|
||||||
|
}
|
||||||
|
if (line.startsWith("result:")) {
|
||||||
|
return CardTestMultiPlayerBase.ExpectedType.RESULT;
|
||||||
|
}
|
||||||
|
if (line.startsWith("life:")) {
|
||||||
|
return CardTestMultiPlayerBase.ExpectedType.LIFE;
|
||||||
|
}
|
||||||
|
if (line.startsWith("battlefield:")) {
|
||||||
|
return CardTestMultiPlayerBase.ExpectedType.BATTLEFIELD;
|
||||||
|
}
|
||||||
|
if (line.startsWith("graveyard:")) {
|
||||||
|
return CardTestMultiPlayerBase.ExpectedType.GRAVEYARD;
|
||||||
|
}
|
||||||
|
return CardTestMultiPlayerBase.ExpectedType.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseType(ExpectedType type, String line) {
|
||||||
|
if (type.equals(CardTestMultiPlayerBase.ExpectedType.TURN_NUMBER)) {
|
||||||
|
int turn = getIntParam(line, 1);
|
||||||
|
Assert.assertEquals("Turn numbers are not equal", turn, currentGame.getTurnNum());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type.equals(CardTestMultiPlayerBase.ExpectedType.RESULT)) {
|
||||||
|
String expected = getStringParam(line, 1);
|
||||||
|
String actual = "draw";
|
||||||
|
if (currentGame.getWinner().equals("Player ComputerA is the winner")) {
|
||||||
|
actual = "won";
|
||||||
|
} else if (currentGame.getWinner().equals("Player ComputerB is the winner")) {
|
||||||
|
actual = "lost";
|
||||||
|
}
|
||||||
|
Assert.assertEquals("Game results are not equal", expected, actual);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type.equals(CardTestMultiPlayerBase.ExpectedType.LIFE)) {
|
||||||
|
String player = getStringParam(line, 1);
|
||||||
|
int expected = getIntParam(line, 2);
|
||||||
|
if (player.equals("ComputerA")) {
|
||||||
|
int actual = currentGame.getPlayer(playerA.getId()).getLife();
|
||||||
|
Assert.assertEquals("Life amounts are not equal", expected, actual);
|
||||||
|
} else if (player.equals("ComputerB")) {
|
||||||
|
int actual = currentGame.getPlayer(playerB.getId()).getLife();
|
||||||
|
Assert.assertEquals("Life amounts are not equal", expected, actual);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Wrong player in 'life' line, player=" + player + ", line=" + line);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type.equals(CardTestMultiPlayerBase.ExpectedType.BATTLEFIELD)) {
|
||||||
|
String playerName = getStringParam(line, 1);
|
||||||
|
String cardName = getStringParam(line, 2);
|
||||||
|
int expectedCount = getIntParam(line, 3);
|
||||||
|
Player player = null;
|
||||||
|
if (playerName.equals("ComputerA")) {
|
||||||
|
player = currentGame.getPlayer(playerA.getId());
|
||||||
|
} else if (playerName.equals("ComputerB")) {
|
||||||
|
player = currentGame.getPlayer(playerB.getId());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Wrong player in 'battlefield' line, player=" + player + ", line=" + line);
|
||||||
|
}
|
||||||
|
int actualCount = 0;
|
||||||
|
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
|
||||||
|
if (permanent.getControllerId().equals(player.getId())) {
|
||||||
|
if (permanent.getName().equals(cardName)) {
|
||||||
|
actualCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertEquals("(Battlefield) Card counts are not equal (" + cardName + ")", expectedCount, actualCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type.equals(CardTestMultiPlayerBase.ExpectedType.GRAVEYARD)) {
|
||||||
|
String playerName = getStringParam(line, 1);
|
||||||
|
String cardName = getStringParam(line, 2);
|
||||||
|
int expectedCount = getIntParam(line, 3);
|
||||||
|
Player player = null;
|
||||||
|
if (playerName.equals("ComputerA")) {
|
||||||
|
player = currentGame.getPlayer(playerA.getId());
|
||||||
|
} else if (playerName.equals("ComputerB")) {
|
||||||
|
player = currentGame.getPlayer(playerB.getId());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Wrong player in 'graveyard' line, player=" + player + ", line=" + line);
|
||||||
|
}
|
||||||
|
int actualCount = 0;
|
||||||
|
for (Card card : player.getGraveyard().getCards(currentGame)) {
|
||||||
|
if (card.getName().equals(cardName)) {
|
||||||
|
actualCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertEquals("(Graveyard) Card counts are not equal (" + cardName + ")", expectedCount, actualCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIntParam(String line, int index) {
|
||||||
|
String[] params = line.split(":");
|
||||||
|
if (index > params.length - 1) {
|
||||||
|
throw new IllegalArgumentException("Not correct line: " + line);
|
||||||
|
}
|
||||||
|
return Integer.parseInt(params[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStringParam(String line, int index) {
|
||||||
|
String[] params = line.split(":");
|
||||||
|
if (index > params.length - 1) {
|
||||||
|
throw new IllegalArgumentException("Not correct line: " + line);
|
||||||
|
}
|
||||||
|
return params[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkPermanentPT(Player player, String cardName, int power, int toughness, Filter.ComparisonScope scope) {
|
||||||
|
if (currentGame == null) {
|
||||||
|
throw new IllegalStateException("Current game is null");
|
||||||
|
}
|
||||||
|
if (scope.equals(Filter.ComparisonScope.All)) {
|
||||||
|
throw new UnsupportedOperationException("ComparisonScope.All is not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) {
|
||||||
|
if (permanent.getName().equals(cardName)) {
|
||||||
|
Assert.assertEquals("Power is not the same", power, permanent.getPower().getValue());
|
||||||
|
Assert.assertEquals("Toughness is not the same", toughness, permanent.getToughness().getValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void skipInitShuffling() {
|
||||||
|
gameOptions.skipInitShuffling = true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue