Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions client/src/main/java/org/moparforia/client/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import java.io.IOException;
import java.text.ParseException;
import java.util.concurrent.Callable;
import java.util.prefs.Preferences;
import java.util.Date;
import java.text.SimpleDateFormat;


@CommandLine.Command(
Expand Down Expand Up @@ -41,6 +44,9 @@ public class Launcher implements Callable<Void> {
@CommandLine.Option(names = {"--verbose", "-v"}, description = "Set if you want verbose information")
private static boolean verbose = false;

@CommandLine.Option(names = {"--reset", "-r"}, description = "Reset user preferences at launch")
private static boolean reset = false;

public static boolean debug() {
return verbose;
}
Expand All @@ -49,6 +55,42 @@ public static boolean isUsingCustomServer() {
return true;//instance.serverBox.isSelected();
}

public void loadPreferences() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move all this Preferences logic into a separate class and add getters/setters for individual properties, this way we can handle all the logic for one property being unknown there. It will be also easier to test, since we could be mocking individual methods in that new class instead of the entire properties.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getters could return Optional and the individual getters could work like this:

  • Is the property in loaded properties?
    • Yes, return the property
    • Not, return empty Optional

Preferences prefs = Preferences.userRoot().node(this.getClass().getName());
long last_time = prefs.getLong("timestamp", 0);
String last_version = prefs.get("version", "unknown"); // TODO: check version
String last_hostname = prefs.get("hostname", "");
int last_port = prefs.getInt("port", 0);
if (!last_hostname.isEmpty() && last_port != 0) {
hostname = last_hostname;
port = last_port;
System.out.printf("Successfully loaded old user preferences written with v%s at %s\n",
last_version, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(last_time));
} else {
System.err.println("No old user preferences found. Using the default settings...");
}
}

public void savePreferences() {
Preferences prefs = Preferences.userRoot().node(this.getClass().getName());
System.out.println("this.getClass().getName()=="+this.getClass().getName());

prefs.putLong("timestamp", new Date().getTime());
prefs.put("version", Launcher.class.getPackage().getImplementationVersion());
prefs.put("hostname", hostname);
prefs.putInt("port", port);
System.out.println("User preferences have been saved successfully");
}

public void resetPreferences() {
Preferences prefs = Preferences.userRoot().node(this.getClass().getName());
prefs.remove("timestamp");
prefs.remove("version");
prefs.remove("hostname");
prefs.remove("port");
System.out.println("Removed old preferences as requested by user");
}

public static void main(String... args) {
Launcher launcher = new Launcher();
new CommandLine(launcher)
Expand Down Expand Up @@ -113,8 +155,13 @@ private String[] login(JFrame frame) {
@Override
public Void call() throws Exception{
JFrame frame = createFrame();
// Remove preferences if requested
if (reset) {
resetPreferences();
}
if (hostname.isEmpty() || port == 0) {
// Determine which of these was actually false
loadPreferences();
String temp_hostname = hostname.isEmpty() ? DEFAULT_SERVER : hostname;
int temp_port = port == 0 ? DEFAULT_PORT : port;
if (!showSettingDialog(frame, temp_hostname, temp_port)) {
Expand All @@ -123,6 +170,7 @@ public Void call() throws Exception{
return null;
}
}
savePreferences();

launchGame(frame, hostname, port, lang, verbose);
return null;
Expand Down
173 changes: 173 additions & 0 deletions client/src/test/java/org/moparforia/client/UserPreferencesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
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 java.util.prefs.Preferences;

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 loading/saving/resetting userPreferences works as expected
*/
@ExtendWith(MockitoExtension.class)
class UserPreferencesTest {

private Launcher launcher;

private CommandLine cmd;
private StringWriter stdOut;
private StringWriter stdErr;

@BeforeEach
void setUp() throws Exception {
// Mock game
launcher = mock(Launcher.class, withSettings()
.lenient()
.withoutAnnotations());

// Use real methods
doCallRealMethod().when(launcher).call();
doCallRealMethod().when(launcher).setPort(anyInt());
doCallRealMethod().when(launcher).setHostname(anyString());

// Get rid of old preferences before test
Preferences prefs = Preferences.userRoot().node("org.moparforia.client.Launcher");
prefs.remove("timestamp");
prefs.remove("version");
prefs.remove("hostname");
prefs.remove("port");
//prefs.remove("lang");

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 testPreferencesInvalidCLI() {
assertNotEquals(0, cmd.execute("-r", "test"));
assertNotEquals(0, cmd.execute("--reset", "test"));
assertNotEquals(0, cmd.execute("-r=test"));
assertNotEquals(0, cmd.execute("--reset=test"));
}

@Test
void testPreferencesValidCLI() {
// Prepare Test
Preferences prefs = Preferences.userRoot().node("org.moparforia.client.Launcher");
prefs.put("version", "1.2.3");
prefs.put("hostname", "localhost");
prefs.putInt("port", 4321);
//prefs.putInt("lang", "en");

// Normally launch Game
try {
doAnswer((invocaton) -> {
launcher.setHostname(invocaton.getArgument(1));
launcher.setPort(invocaton.getArgument(2));
return true;
}).when(launcher).showSettingDialog(any(JFrame.class), anyString(), anyInt());

} catch (ParseException e) {
//fail("showSettingDialog should not have thrown an Exception"); // TODO: fix
}
assertEquals(0, cmd.execute("-r"));
verify(launcher).launchGame(any(),
eq(Launcher.DEFAULT_SERVER),
eq(Launcher.DEFAULT_PORT),
eq(Launcher.Language.EN_US),
anyBoolean());

// Dismiss settings dialog TODO: fix this
/*try {
doAnswer((invocaton) -> {
return false;
}).when(launcher).showSettingDialog(any(JFrame.class), anyString(), anyInt());
} catch (ParseException e) {
//fail("showSettingDialog should not have thrown an Exception"); // TODO: fix
}
assertNotEquals(0, cmd.execute("--reset"));
assertEquals("unknown", prefs.get("version", "unknown"));
assertEquals("", prefs.get("hostname", ""));
assertEquals(0, prefs.getInt("port", 0));
assertEquals("", prefs.get("lang", ""));*/
}

@Test
void testSavePreferences() {
Preferences prefs = Preferences.userRoot().node("org.moparforia.client.Launcher");
/*try {
doAnswer((invocaton) -> {
launcher.setHostname(invocaton.getArgument(1));
launcher.setPort(invocaton.getArgument(2));
return true;
}).when(launcher).showSettingDialog(any(JFrame.class), anyString(), anyInt());

} catch (ParseException e) {
//fail("showSettingDialog should not have thrown an Exception"); // TODO: fix
}
assertEquals(0, cmd.execute());
verify(launcher).launchGame(any(),
eq(Launcher.DEFAULT_SERVER),
eq(Launcher.DEFAULT_PORT),
eq(Launcher.Language.EN_US),
anyBoolean());
assertEquals(Launcher.class.getPackage().getImplementationVersion(), prefs.get("version", "unknown"));
assertEquals(Launcher.DEFAULT_SERVER, prefs.get("hostname", ""));
assertEquals(Launcher.DEFAULT_PORT, prefs.getInt("port", 0));
//assertEquals(Launcher.Language.EN_US, prefs.get("lang", ""));*/
}

@Test
void testLoadPreferences() {
Preferences prefs = Preferences.userRoot().node("org.moparforia.client.Launcher");
prefs.put("version", "1.2.3");
prefs.put("hostname", "localhost");
prefs.putInt("port", 4321);
//prefs.putInt("lang", "en");

/*try {
doAnswer((invocaton) -> {
launcher.setHostname(invocaton.getArgument(1));
launcher.setPort(invocaton.getArgument(2));
return true;
}).when(launcher).showSettingDialog(any(JFrame.class), anyString(), anyInt());

} catch (ParseException e) {
//fail("showSettingDialog should not have thrown an Exception"); // TODO: fix
}
assertEquals(0, cmd.execute());
try {
verify(launcher).showSettingDialog(any(),
eq("localhost"),
eq(4321)
//anyString(),
);
} catch (ParseException e) {
//fail("showSettingDialog should not have thrown an Exception"); // TODO: fix
}*/

}
}