diff --git a/client/client.iml b/client/client.iml
index a08f2bd3..fafe275d 100644
--- a/client/client.iml
+++ b/client/client.iml
@@ -4,13 +4,38 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/pom.xml b/client/pom.xml
index ce447e40..532d940a 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -32,6 +32,27 @@
info.picocli
picocli
+
+ org.moparforia
+ shared
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
diff --git a/client/src/main/java/org/moparforia/client/Launcher.java b/client/src/main/java/org/moparforia/client/Launcher.java
index 039c53fb..75d983ac 100644
--- a/client/src/main/java/org/moparforia/client/Launcher.java
+++ b/client/src/main/java/org/moparforia/client/Launcher.java
@@ -2,24 +2,25 @@
import picocli.CommandLine;
+import org.moparforia.shared.ManifestVersionProvider;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
+import java.io.IOException;
import java.text.ParseException;
import java.util.concurrent.Callable;
-/**
- * Playforia
- * 28.5.2013
- */
+
@CommandLine.Command(
description = "Starts Minigolf Client",
- name = "client", mixinStandardHelpOptions = true
+ name = "client",
+ mixinStandardHelpOptions = true,
+ versionProvider = ManifestVersionProvider.class
)
public class Launcher implements Callable {
- private static final String DEFAULT_SERVER = "127.0.0.1";
- private static final int DEFAULT_PORT = 4242;
+ public static final String DEFAULT_SERVER = "127.0.0.1";
+ public static final int DEFAULT_PORT = 4242;
// CLI options
@CommandLine.Option(names = {"--hostname", "-ip"},
@@ -33,9 +34,8 @@ public class Launcher implements Callable {
private int port;
@CommandLine.Option(names = {"--lang", "-l"},
- description = "Sets language of the game, available values: ${COMPLETION-CANDIDATES}",
- defaultValue = "EN_US")
- private Language lang;
+ description = "Sets language of the game, available values:\n ${COMPLETION-CANDIDATES}")
+ private Language lang = Language.EN_US;
@CommandLine.Option(names = {"--verbose", "-v"}, description = "Set if you want verbose information")
private static boolean verbose = false;
@@ -51,7 +51,9 @@ public static boolean isUsingCustomServer() {
public static void main(String... args) throws Exception {
Launcher launcher = new Launcher();
try {
- CommandLine.ParseResult parseResult = new CommandLine(launcher).parseArgs(args);
+ CommandLine.ParseResult parseResult = new CommandLine(launcher)
+ .setCaseInsensitiveEnumValuesAllowed(true)
+ .parseArgs(args);
if (!CommandLine.printHelpIfRequested(parseResult)) {
launcher.call();
}
@@ -61,7 +63,7 @@ public static void main(String... args) throws Exception {
}
}
- private boolean showSettingDialog(JFrame frame, String server, int port) throws ParseException {
+ public boolean showSettingDialog(JFrame frame, String server, int port) throws ParseException {
JPanel pane = new JPanel();
pane.setLayout(new GridLayout(4, 1));
@@ -117,10 +119,7 @@ private String[] login(JFrame frame) {
@Override
public Void call() throws Exception{
- JFrame frame = new JFrame();
- frame.setTitle("Minigolf");
- Image img = ImageIO.read(getClass().getResource("/icons/playforia.png"));
- frame.setIconImage(img);
+ JFrame frame = createFrame();
if (hostname.isEmpty() || port == 0) {
// Determine which of these was actually false
String temp_hostname = hostname.isEmpty() ? DEFAULT_SERVER : hostname;
@@ -130,10 +129,33 @@ public Void call() throws Exception{
}
}
- new Game(frame, hostname, port, lang.toString(), verbose);
+ launchGame(frame, hostname, port, lang, verbose);
return null;
}
+ public JFrame createFrame() throws IOException {
+ JFrame frame = new JFrame();
+ frame.setTitle("Minigolf");
+ Image img = loadIcon();
+ frame.setIconImage(img);
+ return frame;
+ }
+
+ public Game launchGame(JFrame frame, String hostname, int port, Language lang, boolean verbose) {
+ return new Game(frame, hostname, port, lang.toString(), verbose);
+ }
+
+ public Image loadIcon() throws IOException {
+ return ImageIO.read(getClass().getResource("/icons/playforia.png"));
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
enum Language {
EN_US("en_US"),
diff --git a/client/src/test/java/org/moparforia/client/LauncherCLITest.java b/client/src/test/java/org/moparforia/client/LauncherCLITest.java
new file mode 100644
index 00000000..79aad260
--- /dev/null
+++ b/client/src/test/java/org/moparforia/client/LauncherCLITest.java
@@ -0,0 +1,126 @@
+package org.moparforia.client;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+import picocli.CommandLine;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.ParseException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+/**
+ * Tests that CLI parsing works as expected, it doesn't test the main method, but it tests the picocli annotations
+ */
+@ExtendWith(MockitoExtension.class)
+class LauncherCLITest {
+
+ private Launcher launcher;
+
+ private CommandLine cmd;
+ private StringWriter stdOut;
+ private StringWriter stdErr;
+
+ @BeforeEach
+ void setUp() throws ParseException, IOException {
+ // Mock game
+ launcher = spy(new Launcher());
+ lenient().doReturn(mock(Game.class)).when(launcher).launchGame(any(JFrame.class), anyString(), anyInt(), any(), anyBoolean());
+
+ // Mock creating JFrame
+ lenient().doReturn(mock(JFrame.class)).when(launcher).createFrame();
+
+ // Mock settings dialog
+ lenient().doAnswer((invocaton) -> {
+ launcher.setPort(invocaton.getArgument(2));
+ launcher.setHostname(invocaton.getArgument(1));
+ return true;
+ }).when(launcher).showSettingDialog(any(JFrame.class), anyString(), anyInt());
+
+ cmd = new CommandLine(launcher).setCaseInsensitiveEnumValuesAllowed(true);
+
+ stdOut = new StringWriter();
+ stdErr = new StringWriter();
+
+ cmd.setOut(new PrintWriter(stdOut));
+ cmd.setErr(new PrintWriter(stdErr));
+ }
+
+ @AfterEach
+ void tearDown() {
+ clearInvocations(launcher);
+ }
+
+ @Test
+ void testInvalidPort() {
+ assertNotEquals(0, cmd.execute("-p", "test"));
+ assertNotEquals(0, cmd.execute("--port=test"));
+ assertNotEquals(0, cmd.execute("-p"));
+ }
+
+ @Test
+ void testInvalidLang() {
+ assertNotEquals(0, cmd.execute("-l", "cs_CZ"));
+ assertNotEquals(0, cmd.execute("-l", "en"));
+ }
+
+ @Test
+ void testValidLang() {
+ assertEquals(0, cmd.execute("-l", "en_US"));
+ verify(launcher).launchGame(any(),
+ eq(Launcher.DEFAULT_SERVER),
+ eq(Launcher.DEFAULT_PORT),
+ eq(Launcher.Language.EN_US),
+ anyBoolean());
+
+ assertEquals(0, cmd.execute("--lang=Fi_fI"));
+ verify(launcher).launchGame(any(),
+ eq(Launcher.DEFAULT_SERVER),
+ eq(Launcher.DEFAULT_PORT),
+ eq(Launcher.Language.FI_FI),
+ anyBoolean());
+ }
+
+ @Test
+ void testValidPortAndHostname() {
+ assertEquals(0, cmd.execute("-p", "1111", "-ip", "128.128.128.128"));
+ verify(launcher).launchGame(any(), eq("128.128.128.128"), eq(1111), any(), anyBoolean());
+
+ assertEquals(0, cmd.execute("-p=2222", "-ip=127.127.127.127"));
+ verify(launcher).launchGame(any(), eq("127.127.127.127"), eq(2222), any(), anyBoolean());
+
+ assertEquals(0, cmd.execute("-p=3333", "-ip=126.126.126.126"));
+ verify(launcher).launchGame(any(), eq("126.126.126.126"), eq(3333), any(), anyBoolean());
+ }
+
+ @Test
+ void testOnlyPort() {
+ assertEquals(0, cmd.execute("-p", "1111"));
+ verify(launcher).launchGame(any(), eq(Launcher.DEFAULT_SERVER), eq(1111), any(), anyBoolean());
+ }
+
+ @Test
+ void testOnlyHostname() {
+ assertEquals(0, cmd.execute("-ip", "127.127.127.127"));
+ verify(launcher).launchGame(any(), eq("127.127.127.127"), eq(Launcher.DEFAULT_PORT), any(), anyBoolean());
+ }
+
+ @Test
+ void testDefaultValues() {
+ assertEquals(0, cmd.execute());
+ verify(launcher).launchGame(any(),
+ eq(Launcher.DEFAULT_SERVER),
+ eq(Launcher.DEFAULT_PORT),
+ eq(Launcher.Language.EN_US),
+ eq(false));
+ }
+}
\ No newline at end of file
diff --git a/client/src/test/java/org/moparforia/client/ResourceLoadTest.java b/client/src/test/java/org/moparforia/client/ResourceLoadTest.java
new file mode 100644
index 00000000..69ed4972
--- /dev/null
+++ b/client/src/test/java/org/moparforia/client/ResourceLoadTest.java
@@ -0,0 +1,22 @@
+package org.moparforia.client;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+
+/**
+ * Tests that resources can be loaded
+ */
+class ResourceLoadTest {
+
+ /**
+ * Tests that Launcher icon can be loaded
+ */
+ @Test
+ void testLoadIcon() {
+ Launcher launcher = new Launcher();
+ assertDoesNotThrow(launcher::loadIcon);
+ }
+
+}
\ No newline at end of file
diff --git a/editor/editor.iml b/editor/editor.iml
index 03fa41c4..4df9cb35 100644
--- a/editor/editor.iml
+++ b/editor/editor.iml
@@ -4,7 +4,6 @@
-
diff --git a/pom.xml b/pom.xml
index 0475be3a..d4c23da5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,6 +48,13 @@
${project.mainClass}
+
+ ${project.artifactId}
+ ${project.version}
+ ${project.artifactId}
+ ${project.version}
+ ${project.groupId}
+
@@ -74,6 +81,10 @@
exec-maven-plugin
3.0.0
+
+ maven-surefire-plugin
+ 2.22.2
+
@@ -106,6 +117,26 @@
picocli
${picocli.version}
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.6.2
+ test
+
+
+ org.mockito
+ mockito-core
+ 3.5.10
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ 3.5.10
+ test
+
diff --git a/server/pom.xml b/server/pom.xml
index 148de51c..ef406e0e 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -40,6 +40,23 @@
info.picocli
picocli
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
diff --git a/server/server.iml b/server/server.iml
index a8a3312c..37695179 100644
--- a/server/server.iml
+++ b/server/server.iml
@@ -5,6 +5,8 @@
+
+
@@ -15,5 +17,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/server/src/main/java/org/moparforia/server/Launcher.java b/server/src/main/java/org/moparforia/server/Launcher.java
index ae2cd397..236cfb05 100644
--- a/server/src/main/java/org/moparforia/server/Launcher.java
+++ b/server/src/main/java/org/moparforia/server/Launcher.java
@@ -1,24 +1,28 @@
package org.moparforia.server;
+import org.moparforia.shared.ManifestVersionProvider;
import picocli.CommandLine;
import java.util.concurrent.Callable;
@CommandLine.Command(
description = "Starts Minigolf Server",
- name = "server", mixinStandardHelpOptions = true
+ name = "server",
+ mixinStandardHelpOptions = true,
+ versionProvider = ManifestVersionProvider.class
)
public class Launcher implements Callable {
+ public static final String DEFAULT_HOST = "0.0.0.0";
+ public static final int DEFAULT_PORT = 4242;
+
@CommandLine.Option(names = {"--hostname", "-ip"},
- description = "Sets server hostname",
- defaultValue = "0.0.0.0")
- private String host;
+ description = "Sets server hostname")
+ private String host = DEFAULT_HOST;
@CommandLine.Option(names = {"--port", "-p"},
- description = "Sets server port",
- defaultValue = "4242")
- private int port;
+ description = "Sets server port")
+ private int port = DEFAULT_PORT;
public static void main(String... args) {
Launcher launcher = new Launcher();
@@ -35,7 +39,11 @@ public static void main(String... args) {
@Override
public Void call() {
- new Server(host, port).start();
+ getServer(host, port).start();
return null;
}
+
+ public Server getServer(String host, int port) {
+ return new Server(host, port);
+ }
}
diff --git a/server/src/test/java/org/moparforia/server/LauncherCLITest.java b/server/src/test/java/org/moparforia/server/LauncherCLITest.java
new file mode 100644
index 00000000..a95f2723
--- /dev/null
+++ b/server/src/test/java/org/moparforia/server/LauncherCLITest.java
@@ -0,0 +1,87 @@
+package org.moparforia.server;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+import picocli.CommandLine;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * Tests that CLI parsing works as expected, it doesn't test the main method, but it tests the picocli annotations
+ */
+@ExtendWith(MockitoExtension.class)
+class LauncherCLITest {
+ private Launcher launcher;
+
+ private CommandLine cmd;
+ private StringWriter stdErr;
+ private StringWriter stdOut;
+
+ @BeforeEach
+ void setUp() {
+ // Mock Launcher instance
+ launcher = spy(new Launcher());
+ lenient().doReturn(mock(Server.class)).when(launcher).getServer(anyString(), anyInt());
+
+ cmd = new CommandLine(launcher).setCaseInsensitiveEnumValuesAllowed(true);
+
+ stdOut = new StringWriter();
+ stdErr = new StringWriter();
+
+ cmd.setOut(new PrintWriter(stdOut));
+ cmd.setErr(new PrintWriter(stdErr));
+ }
+
+ @AfterEach
+ void tearDown() {
+ clearInvocations(launcher);
+ }
+
+ @Test
+ void testInvalidPort() {
+ assertNotEquals(0, cmd.execute("-p", "test"));
+ assertNotEquals(0, cmd.execute("--port=test"));
+ assertNotEquals(0, cmd.execute("-p"));
+
+ verify(launcher, never()).getServer(anyString(), anyInt());
+ }
+
+ @Test
+ void testValidPortAndHostname() {
+ assertEquals(0, cmd.execute("-p", "1111", "-ip", "128.128.128.128"));
+ verify(launcher).getServer(eq("128.128.128.128"), eq(1111));
+
+ assertEquals(0, cmd.execute("-p=2222", "-ip=127.127.127.127"));
+ verify(launcher).getServer(eq("127.127.127.127"), eq(2222));
+
+ assertEquals(0, cmd.execute("-p=3333", "-ip=126.126.126.126"));
+ verify(launcher).getServer(eq("126.126.126.126"), eq(3333));
+ }
+
+ @Test
+ void testOnlyPort() {
+ assertEquals(0, cmd.execute("-p", "1111"));
+ verify(launcher).getServer(eq(Launcher.DEFAULT_HOST), eq(1111));
+ }
+
+ @Test
+ void testOnlyHostname() {
+ assertEquals(0, cmd.execute("-ip", "127.127.127.127"));
+ verify(launcher).getServer(eq("127.127.127.127"), eq(Launcher.DEFAULT_PORT));
+ }
+
+ @Test
+ void testDefaultValues() {
+ assertEquals(0, cmd.execute());
+ verify(launcher).getServer(eq(Launcher.DEFAULT_HOST), eq(Launcher.DEFAULT_PORT));
+ }
+}
\ No newline at end of file
diff --git a/shared/pom.xml b/shared/pom.xml
index b64a4355..c7eb7f3e 100644
--- a/shared/pom.xml
+++ b/shared/pom.xml
@@ -24,9 +24,13 @@
morphia
provided
+
+ info.picocli
+ picocli
+ provided
+
- src
org.apache.maven.plugins
diff --git a/shared/shared.iml b/shared/shared.iml
index 84b089b8..9d9c4dbf 100644
--- a/shared/shared.iml
+++ b/shared/shared.iml
@@ -13,5 +13,6 @@
+
\ No newline at end of file
diff --git a/shared/src/main/java/org/moparforia/shared/ManifestVersionProvider.java b/shared/src/main/java/org/moparforia/shared/ManifestVersionProvider.java
new file mode 100644
index 00000000..ae92aef2
--- /dev/null
+++ b/shared/src/main/java/org/moparforia/shared/ManifestVersionProvider.java
@@ -0,0 +1,11 @@
+package org.moparforia.shared;
+
+import picocli.CommandLine;
+
+public class ManifestVersionProvider implements CommandLine.IVersionProvider {
+ @Override
+ public String[] getVersion() {
+ String version = ManifestVersionProvider.class.getPackage().getImplementationVersion();
+ return new String[] {"${COMMAND-FULL-NAME} " + version};
+ }
+}