diff --git a/Mage.Common/src/mage/interfaces/Server.java b/Mage.Common/src/mage/interfaces/Server.java
index a6d3b7f3956..7cc8ade3c6e 100644
--- a/Mage.Common/src/mage/interfaces/Server.java
+++ b/Mage.Common/src/mage/interfaces/Server.java
@@ -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;
}
diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml
index d746dea46a3..0146a43de4f 100644
--- a/Mage.Server/pom.xml
+++ b/Mage.Server/pom.xml
@@ -88,11 +88,6 @@
${project.version}
runtime
-
- org.jbehave
- jbehave-core
- 3.2-beta-1
-
diff --git a/Mage.Server/src/main/java/mage/server/ServerImpl.java b/Mage.Server/src/main/java/mage/server/ServerImpl.java
index d0a7abbf145..59bc37a5f29 100644
--- a/Mage.Server/src/main/java/mage/server/ServerImpl.java
+++ b/Mage.Server/src/main/java/mage/server/ServerImpl.java
@@ -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);
+ }
+
}
diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java
index 7739f94f110..9f4484ed46d 100644
--- a/Mage.Server/src/main/java/mage/server/game/GameController.java
+++ b/Mage.Server/src/main/java/mage/server/game/GameController.java
@@ -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 cards = new HashSet();
+ 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;
diff --git a/Mage.Server/src/main/java/mage/server/game/GameManager.java b/Mage.Server/src/main/java/mage/server/game/GameManager.java
index 77da7725e4a..a28983c5f7a 100644
--- a/Mage.Server/src/main/java/mage/server/game/GameManager.java
+++ b/Mage.Server/src/main/java/mage/server/game/GameManager.java
@@ -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);
+ }
}
diff --git a/Mage.Server/src/test/java/mage/server/bdd/MageEmbedder.java b/Mage.Server/src/test/java/mage/server/bdd/MageEmbedder.java
deleted file mode 100644
index 4e27d6791d9..00000000000
--- a/Mage.Server/src/test/java/mage/server/bdd/MageEmbedder.java
+++ /dev/null
@@ -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 traversalPaths = new ArrayList();
- 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() {
- return new InstanceStepsFactory(configuration(), new MageSteps()).createCandidateSteps();
- }
-}
\ No newline at end of file
diff --git a/Mage.Server/src/test/java/mage/server/bdd/MageSteps.java b/Mage.Server/src/test/java/mage/server/bdd/MageSteps.java
deleted file mode 100644
index 7c59f3c5321..00000000000
--- a/Mage.Server/src/test/java/mage/server/bdd/MageSteps.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/Mage.Server/src/test/java/mage/server/bdd/MageStoryRunner.java b/Mage.Server/src/test/java/mage/server/bdd/MageStoryRunner.java
deleted file mode 100644
index f8c142aa1de..00000000000
--- a/Mage.Server/src/test/java/mage/server/bdd/MageStoryRunner.java
+++ /dev/null
@@ -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 storyPaths = (new StoryFinder()).findPaths("src/test/java", asList("stories/land.story"), null);
- System.out.println("Found stories count: " + storyPaths.size());
- embedder.runStoriesAsPaths(storyPaths);
- }
-}
diff --git a/Mage.Server/src/test/java/stories/land.story b/Mage.Server/src/test/java/stories/land.story
deleted file mode 100644
index af024677a26..00000000000
--- a/Mage.Server/src/test/java/stories/land.story
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/Mage.Tests/UW Control.dck b/Mage.Tests/UW Control.dck
new file mode 100644
index 00000000000..3033c885668
--- /dev/null
+++ b/Mage.Tests/UW Control.dck
@@ -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
diff --git a/Mage.Tests/pom.xml b/Mage.Tests/pom.xml
new file mode 100644
index 00000000000..f3d31fd2e62
--- /dev/null
+++ b/Mage.Tests/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+
+ org.mage
+ mage-root
+ 0.5
+
+
+ Mage-Tests
+ jar
+ Mage Tests
+
+
+
+ ${project.groupId}
+ Mage
+ ${mage-version}
+
+
+ ${project.groupId}
+ Mage-Common
+ ${mage-version}
+
+
+ ${project.groupId}
+ Mage-Sets
+ ${mage-version}
+
+
+ ${project.groupId}
+ Mage-Server
+ ${mage-version}
+
+
+ junit
+ junit
+ 4.8.2
+
+
+
+ log4j
+ log4j
+ 1.2.14
+ jar
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.0.2
+
+ 1.6
+ 1.6
+
+
+
+ maven-resources-plugin
+
+ UTF-8
+
+
+
+
+ mage-tests
+
+
+
+
+
diff --git a/Mage.Tests/src/test/java/org/mage/test/LandTest.java b/Mage.Tests/src/test/java/org/mage/test/LandTest.java
new file mode 100644
index 00000000000..9535a2d0c42
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/LandTest.java
@@ -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();
+ }*/
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/base/MageAPI.java b/Mage.Tests/src/test/java/org/mage/test/base/MageAPI.java
new file mode 100644
index 00000000000..0b88f85fab7
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/base/MageAPI.java
@@ -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();
+ }
+}
diff --git a/Mage.Server/src/test/java/mage/server/bdd/StoryRunPOC.java b/Mage.Tests/src/test/java/org/mage/test/base/MageBase.java
similarity index 57%
rename from Mage.Server/src/test/java/mage/server/bdd/StoryRunPOC.java
rename to Mage.Tests/src/test/java/org/mage/test/base/MageBase.java
index 96f2f1fd373..e00b5144451 100644
--- a/Mage.Server/src/test/java/mage/server/bdd/StoryRunPOC.java
+++ b/Mage.Tests/src/test/java/org/mage/test/base/MageBase.java
@@ -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 playerTypes = new ArrayList();
- 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 playerTypes = new ArrayList();
+ 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;
+ }
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/and/And.java b/Mage.Tests/src/test/java/org/mage/test/bdd/and/And.java
new file mode 100644
index 00000000000..3243bd7ea00
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/and/And.java
@@ -0,0 +1,6 @@
+package org.mage.test.bdd.and;
+
+public class And {
+ public static Phase phase;
+ public static Graveyards graveyards;
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/and/Graveyards.java b/Mage.Tests/src/test/java/org/mage/test/bdd/and/Graveyards.java
new file mode 100644
index 00000000000..2411d87f7b5
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/and/Graveyards.java
@@ -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;
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/and/Phase.java b/Mage.Tests/src/test/java/org/mage/test/bdd/and/Phase.java
new file mode 100644
index 00000000000..53a5a6fbeeb
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/and/Phase.java
@@ -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();
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/given/A.java b/Mage.Tests/src/test/java/org/mage/test/bdd/given/A.java
new file mode 100644
index 00000000000..325891ab54c
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/given/A.java
@@ -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);
+ }
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/given/Given.java b/Mage.Tests/src/test/java/org/mage/test/bdd/given/Given.java
new file mode 100644
index 00000000000..dd8c89e04c1
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/given/Given.java
@@ -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;
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/given/Have.java b/Mage.Tests/src/test/java/org/mage/test/bdd/given/Have.java
new file mode 100644
index 00000000000..e49750c26a3
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/given/Have.java
@@ -0,0 +1,5 @@
+package org.mage.test.bdd.given;
+
+public class Have {
+ public static A a;
+}
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/given/I.java b/Mage.Tests/src/test/java/org/mage/test/bdd/given/I.java
new file mode 100644
index 00000000000..034626aefcc
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/given/I.java
@@ -0,0 +1,5 @@
+package org.mage.test.bdd.given;
+
+public class I {
+ public static Have have;
+}
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/then/Battlefield.java b/Mage.Tests/src/test/java/org/mage/test/bdd/then/Battlefield.java
new file mode 100644
index 00000000000..fe59b119235
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/then/Battlefield.java
@@ -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);
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/then/Then.java b/Mage.Tests/src/test/java/org/mage/test/bdd/then/Then.java
new file mode 100644
index 00000000000..6307c6b5cbc
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/then/Then.java
@@ -0,0 +1,5 @@
+package org.mage.test.bdd.then;
+
+public class Then {
+ public static Battlefield battlefield;
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/when/I.java b/Mage.Tests/src/test/java/org/mage/test/bdd/when/I.java
new file mode 100644
index 00000000000..053c5b69138
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/when/I.java
@@ -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);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/bdd/when/When.java b/Mage.Tests/src/test/java/org/mage/test/bdd/when/When.java
new file mode 100644
index 00000000000..bb995327306
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/bdd/when/When.java
@@ -0,0 +1,5 @@
+package org.mage.test.bdd.when;
+
+public class When {
+ public static I I;
+}
diff --git a/pom.xml b/pom.xml
index 76614ae0df1..e2e3a09f68a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,6 +19,7 @@
Mage.Client
Mage.Plugins
Mage.Server.Plugins
+ Mage.Tests