This commit is contained in:
magenoxx 2010-12-20 01:07:11 +03:00
commit d898c083d4
26 changed files with 457 additions and 173 deletions

View file

@ -39,6 +39,7 @@ import mage.game.GameException;
import mage.interfaces.callback.CallbackServer;
import mage.view.GameTypeView;
import mage.view.TableView;
import mage.view.GameView;
/**
*
@ -94,5 +95,6 @@ public interface Server extends Remote, CallbackServer {
//test methods
public void cheat(UUID gameId, UUID sessionId, UUID playerId, DeckCardLists deckList) throws RemoteException, MageException;
public void cheat(UUID gameId, UUID sessionId, UUID playerId, String cardName) throws RemoteException, MageException;
public GameView getGameView(UUID gameId, UUID sessionId, UUID playerId) throws RemoteException, MageException;
}

View file

@ -88,11 +88,6 @@
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
<version>3.2-beta-1</version>
</dependency>
</dependencies>
<pluginRepositories>

View file

@ -57,6 +57,7 @@ import mage.server.game.TableManager;
import mage.server.util.ThreadExecutor;
import mage.util.Logging;
import mage.view.ChatMessage.MessageColor;
import mage.view.GameView;
import mage.view.TableView;
/**
@ -615,9 +616,31 @@ public class ServerImpl extends RemoteServer implements Server {
}
}
@Override
public void cheat(final UUID gameId, final UUID sessionId, final UUID playerId, final String cardName) throws MageException {
try {
rmiExecutor.execute(
new Runnable() {
@Override
public void run() {
if (testMode)
GameManager.getInstance().cheat(gameId, sessionId, playerId, cardName);
}
}
);
}
catch (Exception ex) {
handleException(ex);
}
}
public void handleException(Exception ex) throws MageException {
logger.log(Level.SEVERE, "", ex);
throw new MageException("Server error");
}
public GameView getGameView(final UUID gameId, final UUID sessionId, final UUID playerId) {
return GameManager.getInstance().getGameView(gameId, sessionId, playerId);
}
}

View file

@ -235,6 +235,17 @@ public class GameController implements GameCallback {
updateGame();
}
public void cheat(UUID sessionId, UUID playerId, String cardName) {
String clazz = Sets.findCard(cardName);
if (clazz != null) {
Card card = CardImpl.createCard(clazz);
Set<Card> cards = new HashSet<Card>();
cards.add(card);
game.loadCards(cards, playerId);
updateGame();
}
}
public void kill(UUID sessionId) {
if (sessionPlayerMap.containsKey(sessionId)) {
gameSessions.get(sessionPlayerMap.get(sessionId)).setKilled();
@ -384,7 +395,7 @@ public class GameController implements GameCallback {
return new GameView(game.getState(), game);
}
private GameView getGameView(UUID playerId) {
public GameView getGameView(UUID playerId) {
GameView gameView = new GameView(game.getState(), game);
gameView.setHand(new CardsView(game.getPlayer(playerId).getHand().getCards(game)));
return gameView;

View file

@ -32,6 +32,7 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import mage.cards.decks.DeckCardLists;
import mage.game.Game;
import mage.view.GameView;
/**
*
@ -112,6 +113,10 @@ public class GameManager {
gameControllers.get(gameId).cheat(sessionId, playerId, deckList);
}
public void cheat(UUID gameId, UUID sessionId, UUID playerId, String cardName) {
gameControllers.get(gameId).cheat(sessionId, playerId, cardName);
}
void timeout(UUID gameId, UUID sessionId) {
gameControllers.get(gameId).timeout(sessionId);
}
@ -120,4 +125,7 @@ public class GameManager {
gameControllers.remove(gameId);
}
public GameView getGameView(UUID gameId, UUID sessionId, UUID playerId) {
return gameControllers.get(gameId).getGameView(playerId);
}
}

View file

@ -1,73 +0,0 @@
package mage.server.bdd;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.embedder.Embedder;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.LoadFromRelativeFile;
import org.jbehave.core.io.StoryResourceNotFound;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.steps.CandidateSteps;
import org.jbehave.core.steps.InstanceStepsFactory;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Contains configuration for working with steps and stories in Mage.
*
* @author nantuko
*/
public class MageEmbedder extends Embedder {
/**
* We meed to extend LoadFromRelativeFile because of bug in replacing slashes
*
* @author nantuko
*/
private class MageStoryFilePath extends LoadFromRelativeFile {
private final StoryFilePath[] traversals;
private final URL location;
public MageStoryFilePath(URL location, StoryFilePath... traversals) {
super(location, traversals);
this.location = location;
this.traversals = traversals;
}
@Override
public String loadResourceAsText(String resourcePath) {
List<String> traversalPaths = new ArrayList<String>();
String locationPath = new File(location.getFile()).getAbsolutePath();
String filePath = locationPath.replace("target\\test-classes", "src/test/java") + "/" + resourcePath;
File file = new File(filePath);
if (file.exists()) {
return loadContent(filePath);
}
throw new StoryResourceNotFound(resourcePath, traversalPaths);
}
}
@Override
public Configuration configuration() {
Class<?> embedderClass = this.getClass();
URL codeLocation = CodeLocations.codeLocationFromClass(embedderClass);
Configuration configuration = new MostUsefulConfiguration()
.useStoryLoader(new MageStoryFilePath(codeLocation, LoadFromRelativeFile.mavenModuleTestStoryFilePath("src/test/java") ))
.useStoryReporterBuilder(new StoryReporterBuilder()
.withCodeLocation(codeLocation)
.withDefaultFormats());
return configuration;
}
@Override
public List<CandidateSteps> candidateSteps() {
return new InstanceStepsFactory(configuration(), new MageSteps()).createCandidateSteps();
}
}

View file

@ -1,38 +0,0 @@
package mage.server.bdd;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
/**
* Defines Mage BDD steps.
*
* @author nantuko
*/
public class MageSteps {
@Given("I'm in the game")
public void inTheGame() {
System.out.println("In the game");
}
@Given("I have an \"$card\" card")
public void hasACard(String card) {
System.out.println("card: " + card);
}
@Given("phase is $own \"$phase\"")
public void hasPhase(String own, String phase) {
System.out.println("phase is: " + own + " -> " + phase);
}
@When("I splay \"$card\"")
public void playCard(String card) {
System.out.println("play a card: " + card);
}
@Then("there is an \"$card\" on $zone")
public void playCard(String card, String zone) {
System.out.println("checking: " + card + ", zone=" + zone);
}
}

View file

@ -1,21 +0,0 @@
package mage.server.bdd;
import org.jbehave.core.io.StoryFinder;
import java.util.List;
import static java.util.Arrays.asList;
/**
* Runs Mage stories (tests)
*
* @author nantuko
*/
public class MageStoryRunner {
public static void main(String[] argv) throws Throwable {
MageEmbedder embedder = new MageEmbedder();
List<String> storyPaths = (new StoryFinder()).findPaths("src/test/java", asList("stories/land.story"), null);
System.out.println("Found stories count: " + storyPaths.size());
embedder.runStoriesAsPaths(storyPaths);
}
}

View file

@ -1,7 +0,0 @@
Scenario: player plays Land on his main phase
Given I'm in the game
And I have an "Island" card
And phase is my "Precombat Main"
When I play "Island"
Then there is an "Island" on battlefield

29
Mage.Tests/UW Control.dck Normal file
View file

@ -0,0 +1,29 @@
NAME:UW Control
2 [ROE:236] Island
1 [ROE:235] Island
1 [ROE:234] Island
2 [ROE:233] Island
2 [CON:15] Path to Exile
3 [ROE:21] Gideon Jura
1 [CON:11] Martial Coup
2 [ZEN:9] Day of Judgment
1 [ZEN:216] Kabira Crossroads
4 [WWK:31] Jace, the Mind Sculptor
3 [M10:64] Mind Spring
3 [WWK:123] Everflowing Chalice
1 [ROE:232] Plains
4 [ROE:53] Wall of Omens
1 [ROE:229] Plains
1 [ROE:230] Plains
1 [ROE:231] Plains
3 [ALA:20] Oblivion Ring
4 [ZEN:70] Spreading Seas
4 [WWK:145] Tectonic Edge
1 [ALA:9] Elspeth, Knight-Errant
2 [ROE:59] Deprive
1 [ZEN:220] Misty Rainforest
4 [WWK:133] Celestial Colonnade
1 [ZEN:211] Arid Mesa
4 [M10:226] Glacial Fortress
1 [WWK:142] Sejiri Steppe
2 [M10:65] Negate

75
Mage.Tests/pom.xml Normal file
View file

@ -0,0 +1,75 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>0.5</version>
</parent>
<artifactId>Mage-Tests</artifactId>
<packaging>jar</packaging>
<name>Mage Tests</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>Mage</artifactId>
<version>${mage-version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>Mage-Common</artifactId>
<version>${mage-version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>Mage-Sets</artifactId>
<version>${mage-version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>Mage-Server</artifactId>
<version>${mage-version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<finalName>mage-tests</finalName>
</build>
<properties/>
</project>

View file

@ -0,0 +1,36 @@
package org.mage.test;
import org.junit.Test;
import org.mage.test.base.MageAPI;
import org.mage.test.bdd.and.And;
import org.mage.test.bdd.given.Given;
import org.mage.test.bdd.then.Then;
import org.mage.test.bdd.when.When;
import static org.mage.test.base.MageAPI.Owner.*;
public class LandTest extends MageAPI {
@Test
public void testPlayingLandInMainPhase() throws Exception {
//TODO: add test framework callback for synchronization and removing Thread.sleep calls
Given.I.have.a.card("Island");
And.phase.is("Precombat Main", mine);
When.I.play("Island");
Then.battlefield.has("Island");
And.graveyards.empty();
}
/*@Test
public void testLightningHelix() throws Exception {
Given.I.have.a.card("Lightning Helix");
And.battlefield.has("Mountain","Plains");
And.phase.is("End of Turn", ai);
And.lifes(20,20);
When.I.play("Lightning Helix");
Then.my.life(23);
And.ai.life(17);
And.my.graveyard.has("Lightning Helix");
And.ai.graveyard.empty();
}*/
}

View file

@ -0,0 +1,53 @@
package org.mage.test.base;
import mage.game.turn.Phase;
import org.junit.BeforeClass;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
/**
* Parent class for all Mage tests.
* Provides basic actions in mage game and assert functions to check game state.
*/
public class MageAPI {
public enum Owner {
mine,
me,
ai
}
@BeforeClass
public static void startServer() throws Exception {
MageBase.getInstance().start();
Thread.sleep(3000);
}
public void giveme(String card) throws Exception {
MageBase.getInstance().giveme(card);
}
public boolean checkIhave(String card) throws Exception {
return MageBase.getInstance().checkIhave(card);
}
public void goToPhase(String phase, Owner owner) {
if ("Precombat Main".equals(phase) && (owner.equals(Owner.mine) || owner.equals(Owner.me))) {
MageBase.getInstance().goToPhase("Precombat Main - play spells and sorceries.");
return;
}
System.err.println("waitForPhase not implemented for phase="+phase+", owner="+owner.name());
throw new NotImplementedException();
}
public void playCard(String cardName) throws Exception {
MageBase.getInstance().playCard(cardName);
}
public boolean checkBattlefield(String cardName) throws Exception {
return MageBase.getInstance().checkBattlefield(cardName);
}
public boolean checkGraveyardsEmpty() throws Exception {
return MageBase.getInstance().checkGraveyardsEmpty();
}
}

View file

@ -1,4 +1,4 @@
package mage.server.bdd;
package org.mage.test.base;
import mage.interfaces.MageException;
import mage.interfaces.Server;
@ -10,28 +10,40 @@ import mage.server.Main;
import mage.sets.Sets;
import mage.util.Logging;
import mage.view.*;
import org.junit.Test;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Proof of concept of running game from tests.\
* Will be removed later when BDD is finished.
* Base for starting Mage server.
* Controls interactions between MageAPI and Mage Server.
*
* @author nantuko
*/
public class StoryRunPOC {
public class MageBase {
/**
* MageBase single instance
*/
private static MageBase fInstance = new MageBase();
private static Logger logger = Logging.getLogger(StoryRunPOC.class.getName());
/**
* Default logger
*/
private static Logger logger = Logging.getLogger(MageBase.class.getName());
public static MageBase getInstance() {
return fInstance;
}
private static UUID sessionId;
private static Server server;
public static Server server;
private static String userName;
private static ServerState serverState;
private static CallbackClientDaemon callbackDaemon;
@ -39,25 +51,26 @@ public class StoryRunPOC {
private static UUID playerId;
private static CardView cardPlayed;
@Test
public void testEmpty() {
private static GameView gameView;
private static String phaseToWait;
private static Object sync = new Object();
}
public void start() throws Exception {
if (server == null) {
String[] args = new String[]{"-testMode=true"};
Main.main(args);
connect("player", "localhost", 17171);
UUID roomId = server.getMainRoomId();
public static void main(String[] argv) throws Exception {
String[] args = new String[] {"-testMode=true"};
Main.main(args);
connect("player", "localhost", 17171);
UUID roomId = server.getMainRoomId();
List<String> playerTypes = new ArrayList<String>();
playerTypes.add("Human");
playerTypes.add("Computer - default");
TableView table = server.createTable(sessionId, roomId, "Two Player Duel", "Limited", playerTypes, null, null);
System.out.println("Cards in the deck: " + Sets.loadDeck("UW Control.dck").getCards().size());
server.joinTable(sessionId, roomId, table.getTableId(), "Human", Sets.loadDeck("UW Control.dck"));
server.joinTable(sessionId, roomId, table.getTableId(), "Computer", Sets.loadDeck("UW Control.dck"));
server.startGame(sessionId, roomId, table.getTableId());
List<String> playerTypes = new ArrayList<String>();
playerTypes.add("Human");
playerTypes.add("Computer - default");
TableView table = server.createTable(sessionId, roomId, "Two Player Duel", "Limited", playerTypes, null, null);
System.out.println("Cards in the deck: " + Sets.loadDeck("UW Control.dck").getCards().size());
server.joinTable(sessionId, roomId, table.getTableId(), "Human", Sets.loadDeck("UW Control.dck"));
server.joinTable(sessionId, roomId, table.getTableId(), "Computer", Sets.loadDeck("UW Control.dck"));
server.startGame(sessionId, roomId, table.getTableId());
}
}
public static void connect(String userName, String serverName, int port) {
@ -94,7 +107,18 @@ public class StoryRunPOC {
} else if (callback.getMethod().equals("gameSelect")) {
GameClientMessage message = (GameClientMessage) callback.getData();
logger.info("SELECT >> " + message.getMessage());
if (!message.getMessage().startsWith("Precombat Main - play spells and sorceries.")) {
if (phaseToWait == null) {
synchronized (sync) {
sync.wait();
}
}
if (!message.getMessage().startsWith(phaseToWait)) {
server.sendPlayerBoolean(gameId, sessionId, false);
} else {
phaseToWait = null;
}
/*if (!message.getMessage().startsWith("Precombat Main - play spells and sorceries.")) {
server.sendPlayerBoolean(gameId, sessionId, false);
} else {
if (cardPlayed == null) {
@ -132,7 +156,8 @@ public class StoryRunPOC {
logger.info(" found land: " + foundLand);
System.exit(0);
}
}
} */
}
} catch (Exception e) {
logger.info(e.getMessage());
@ -149,4 +174,72 @@ public class StoryRunPOC {
logger.log(Level.SEVERE, "Unable to connect to server - ", ex);
}
}
public void giveme(String cardName) throws Exception {
server.cheat(gameId, sessionId, playerId, cardName);
}
public boolean checkIhave(String cardName) throws Exception {
if (cardName == null) {
return false;
}
gameView = server.getGameView(gameId, sessionId, playerId);
for (CardView card : gameView.getHand().values()) {
if (card.getName().equals(cardName)) {
return true;
}
}
return false;
}
public void goToPhase(String phase) {
phaseToWait = phase;
synchronized (sync) {
sync.notify();
}
}
public void playCard(String cardName) throws Exception {
gameView = server.getGameView(gameId, sessionId, playerId);
CardsView cards = gameView.getHand();
CardView cardToPlay = null;
for (CardView card : cards.values()) {
if (card.getName().equals(cardName)) {
cardToPlay = card;
}
}
if (cardToPlay == null) {
throw new IllegalArgumentException("Couldn't find " + cardName + " in the hand.");
}
if (cardToPlay != null) {
logger.info("Playing " + cardToPlay);
server.sendPlayerUUID(gameId, sessionId, cardToPlay.getId());
cardPlayed = cardToPlay;
}
}
public boolean checkBattlefield(String cardName) throws Exception {
gameView = server.getGameView(gameId, sessionId, playerId);
for (PlayerView player: gameView.getPlayers()) {
if (player.getPlayerId().equals(playerId)) {
for (PermanentView permanent : player.getBattlefield().values()) {
if (permanent.getName().equals(cardName)) {
return true;
}
}
}
}
return false;
}
public boolean checkGraveyardsEmpty() throws Exception {
gameView = server.getGameView(gameId, sessionId, playerId);
for (PlayerView player: gameView.getPlayers()) {
if (player.getGraveyard().size() > 0) {
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,6 @@
package org.mage.test.bdd.and;
public class And {
public static Phase phase;
public static Graveyards graveyards;
}

View file

@ -0,0 +1,11 @@
package org.mage.test.bdd.and;
import org.mage.test.base.MageBase;
public class Graveyards {
public static boolean empty() throws Exception {
boolean empty = MageBase.getInstance().checkGraveyardsEmpty();
System.out.println("empty: " + empty);
return empty;
}
}

View file

@ -0,0 +1,20 @@
package org.mage.test.bdd.and;
import org.mage.test.base.MageAPI;
import org.mage.test.base.MageBase;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import static org.mage.test.base.MageAPI.*;
import static org.mage.test.base.MageAPI.Owner.*;
public class Phase {
public static void is(String phase, MageAPI.Owner owner) throws Exception {
if ("Precombat Main".equals(phase) && (owner.equals(mine) || owner.equals(me))) {
MageBase.getInstance().goToPhase("Precombat Main - play spells and sorceries.");
Thread.sleep(3000);
return;
}
System.err.println("waitForPhase not implemented for phase="+phase+", owner="+owner.name());
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,13 @@
package org.mage.test.bdd.given;
import org.mage.test.base.MageBase;
public class A {
public static void card(String cardName) throws Exception {
MageBase.getInstance().giveme(cardName);
Thread.sleep(4000);
if (!MageBase.getInstance().checkIhave(cardName)) {
throw new IllegalStateException("Couldn't find a card in hand: " + cardName);
}
}
}

View file

@ -0,0 +1,8 @@
package org.mage.test.bdd.given;
import org.mage.test.bdd.and.Phase;
public class Given {
public static I I;
public static Phase phase;
}

View file

@ -0,0 +1,5 @@
package org.mage.test.bdd.given;
public class Have {
public static A a;
}

View file

@ -0,0 +1,5 @@
package org.mage.test.bdd.given;
public class I {
public static Have have;
}

View file

@ -0,0 +1,9 @@
package org.mage.test.bdd.then;
import org.mage.test.base.MageBase;
public class Battlefield {
public static boolean has(String cardName) throws Exception {
return MageBase.getInstance().checkBattlefield(cardName);
}
}

View file

@ -0,0 +1,5 @@
package org.mage.test.bdd.then;
public class Then {
public static Battlefield battlefield;
}

View file

@ -0,0 +1,10 @@
package org.mage.test.bdd.when;
import org.mage.test.base.MageBase;
public class I {
public static void play(String cardName) throws Exception {
MageBase.getInstance().playCard(cardName);
Thread.sleep(3000);
}
}

View file

@ -0,0 +1,5 @@
package org.mage.test.bdd.when;
public class When {
public static I I;
}

View file

@ -19,6 +19,7 @@
<module>Mage.Client</module>
<module>Mage.Plugins</module>
<module>Mage.Server.Plugins</module>
<module>Mage.Tests</module>
</modules>
<repositories>