Enhanced test framework for multiplayer games

This commit is contained in:
magenoxx 2012-08-15 22:14:07 +04:00
parent 7b268c7fcb
commit 475666be4c

View file

@ -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;
}
}