diff --git a/pom.xml b/pom.xml
index 9c19232fd..7404cac4b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,6 +90,11 @@
+
+
+ src/test/resources
+
+
diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java
index 7630b99e2..e68eb9a37 100644
--- a/src/main/java/fr/xephi/authme/AuthMe.java
+++ b/src/main/java/fr/xephi/authme/AuthMe.java
@@ -462,7 +462,7 @@ public class AuthMe extends JavaPlugin {
private void setupConsoleFilter() {
if (Settings.removePassword) {
ConsoleFilter filter = new ConsoleFilter();
- ConsoleLogger.getLogger().setFilter(filter);
+ getLogger().setFilter(filter);
Bukkit.getLogger().setFilter(filter);
Logger.getLogger("Minecraft").setFilter(filter);
// Set Log4J Filter
@@ -955,20 +955,10 @@ public class AuthMe extends JavaPlugin {
}
/**
- * Returns the management instance.
+ * Return the management instance.
*/
public Management getManagement() {
return management;
}
- /**
- * Returns the server instance running this plugin. Use this method in favor of {@link
- * AuthMe#getServer()} for testability purposes.
- *
- * @return the server instance
- */
- public Server getGameServer() {
- return super.getServer();
- }
-
}
diff --git a/src/main/java/fr/xephi/authme/ConsoleLogger.java b/src/main/java/fr/xephi/authme/ConsoleLogger.java
index 0bbacbfce..ae8a76619 100644
--- a/src/main/java/fr/xephi/authme/ConsoleLogger.java
+++ b/src/main/java/fr/xephi/authme/ConsoleLogger.java
@@ -3,6 +3,7 @@ package fr.xephi.authme;
import com.google.common.base.Throwables;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils;
+import fr.xephi.authme.util.Wrapper;
import java.io.IOException;
import java.nio.file.Files;
@@ -10,23 +11,17 @@ import java.nio.file.StandardOpenOption;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
-import java.util.logging.Logger;
/**
* The plugin's static logger.
*/
-public class ConsoleLogger {
+public final class ConsoleLogger {
- private static final Logger log = AuthMe.getInstance().getLogger();
+ private static Wrapper wrapper = new Wrapper(AuthMe.getInstance());
private static final DateFormat df = new SimpleDateFormat("[MM-dd HH:mm:ss]");
- /**
- * Returns the plugin's logger.
- *
- * @return Logger
- */
- public static Logger getLogger() {
- return log;
+ private ConsoleLogger() {
+ // Service class
}
/**
@@ -35,7 +30,7 @@ public class ConsoleLogger {
* @param message String
*/
public static void info(String message) {
- log.info(message);
+ wrapper.getLogger().info(message);
if (!Settings.useLogging) {
return;
}
@@ -48,7 +43,7 @@ public class ConsoleLogger {
* @param message String
*/
public static void showError(String message) {
- log.warning(message);
+ wrapper.getLogger().warning(message);
if (!Settings.useLogging) {
return;
}
diff --git a/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java b/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java
index 76bd9d8c7..85e402112 100644
--- a/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java
+++ b/src/main/java/fr/xephi/authme/util/GeoLiteAPI.java
@@ -12,15 +12,15 @@ import java.util.zip.GZIPInputStream;
public class GeoLiteAPI {
- private static final String GEOIP_URL = "http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry" +
- "/GeoIP.dat.gz";
- private static final AuthMe plugin = AuthMe.getInstance();
+ private static final String GEOIP_URL = "http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry"
+ + "/GeoIP.dat.gz";
+ private static final Wrapper wrapper = new Wrapper(AuthMe.getInstance());
private static LookupService lookupService;
/**
* Download (if absent) the GeoIpLite data file and then try to load it.
*
- * @return Boolean True if the data is available, false if not.
+ * @return True if the data is available, false otherwise.
*/
public static boolean isDataAvailable() {
if (lookupService != null) {
@@ -30,15 +30,17 @@ public class GeoLiteAPI {
if (data.exists()) {
try {
lookupService = new LookupService(data);
- plugin.getLogger().info("[LICENSE] This product uses data from the GeoLite API created by MaxMind, " +
+ // TODO ljacqu 20151123: Should this not be output over the ConsoleLogger service?
+ wrapper.getLogger().info("[LICENSE] This product uses data from the GeoLite API created by MaxMind, " +
"available at http://www.maxmind.com");
return true;
} catch (IOException e) {
+ // TODO ljacqu 20151123: Log the exception instead of just swallowing it
return false;
}
}
// Ok, let's try to download the data file!
- plugin.getGameServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
+ wrapper.getServer().getScheduler().runTaskAsynchronously(wrapper.getAuthMe(), new Runnable() {
@Override
public void run() {
try {
diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java
index 3262f2f5e..5efc481f1 100644
--- a/src/main/java/fr/xephi/authme/util/Utils.java
+++ b/src/main/java/fr/xephi/authme/util/Utils.java
@@ -31,7 +31,8 @@ import java.util.zip.GZIPInputStream;
*/
public final class Utils {
- public static AuthMe plugin;
+ private static AuthMe plugin;
+ private static Wrapper wrapper;
private static boolean getOnlinePlayersIsCollection = false;
private static Method getOnlinePlayers;
@@ -39,6 +40,7 @@ public final class Utils {
static {
plugin = AuthMe.getInstance();
+ wrapper = new Wrapper(plugin);
checkGeoIP();
initializeOnlinePlayersIsCollectionField();
}
@@ -65,7 +67,7 @@ public final class Utils {
}
}
}
- plugin.getGameServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
+ wrapper.getServer().getScheduler().runTaskAsynchronously(wrapper.getAuthMe(), new Runnable() {
@Override
public void run() {
try {
@@ -190,6 +192,7 @@ public final class Utils {
}
if (!Settings.isForcedRegistrationEnabled) {
+ // TODO ljacqu 20151123: Use a setter to retrieve things from AuthMe
if (!plugin.database.isAuthAvailable(name)) {
return true;
}
@@ -225,12 +228,12 @@ public final class Utils {
final World world = theWorld;
final Location loc = new Location(world, x, y, z);
- Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
+ Bukkit.getScheduler().scheduleSyncDelayedTask(wrapper.getAuthMe(), new Runnable() {
@Override
public void run() {
AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(pl, loc);
- plugin.getServer().getPluginManager().callEvent(tpEvent);
+ wrapper.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled()) {
pl.teleport(tpEvent.getTo());
}
@@ -325,7 +328,7 @@ public final class Utils {
@SuppressWarnings("deprecation")
public static Player getPlayer(String name) {
name = name.toLowerCase();
- return plugin.getServer().getPlayer(name);
+ return wrapper.getServer().getPlayer(name);
}
public static boolean isNPC(final Entity player) {
@@ -333,6 +336,7 @@ public final class Utils {
if (player.hasMetadata("NPC")) {
return true;
} else if (plugin.combatTagPlus != null
+ // TODO ljacqu 20151123: Use a getter for combatTagPlus in AuthMe instead of using direct field access
&& player instanceof Player
&& plugin.combatTagPlus.getNpcPlayerHelper().isNpc((Player) player)) {
return true;
@@ -347,7 +351,7 @@ public final class Utils {
if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) {
Location spawn = plugin.getSpawnLocation(player);
AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(player, spawn);
- plugin.getServer().getPluginManager().callEvent(tpEvent);
+ wrapper.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled()) {
player.teleport(tpEvent.getTo());
}
diff --git a/src/main/java/fr/xephi/authme/util/Wrapper.java b/src/main/java/fr/xephi/authme/util/Wrapper.java
new file mode 100644
index 000000000..29f806e58
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/util/Wrapper.java
@@ -0,0 +1,34 @@
+package fr.xephi.authme.util;
+
+import fr.xephi.authme.AuthMe;
+import org.bukkit.Server;
+
+import java.util.logging.Logger;
+
+/**
+ * Wrapper for the retrieval of common singletons used throughout the application.
+ * This class simply delegates the calls.
+ */
+public class Wrapper {
+
+ private AuthMe authMe;
+
+ public Wrapper(AuthMe authMe) {
+ this.authMe = authMe;
+ }
+
+ public AuthMe getAuthMe() {
+ return authMe;
+ }
+
+ public Server getServer() {
+ return authMe.getServer();
+ }
+
+ public Logger getLogger() {
+ return authMe.getLogger();
+ }
+
+
+
+}
diff --git a/src/test/java/fr/xephi/authme/AuthMeMockUtil.java b/src/test/java/fr/xephi/authme/AuthMeMockUtil.java
index 905c46303..821157f36 100644
--- a/src/test/java/fr/xephi/authme/AuthMeMockUtil.java
+++ b/src/test/java/fr/xephi/authme/AuthMeMockUtil.java
@@ -1,6 +1,7 @@
package fr.xephi.authme;
import fr.xephi.authme.settings.Messages;
+import fr.xephi.authme.util.Wrapper;
import org.mockito.Mockito;
import java.lang.reflect.Field;
@@ -15,15 +16,18 @@ public final class AuthMeMockUtil {
}
/**
- * Sets the AuthMe plugin instance to a mock object. Use {@link AuthMe#getInstance()} to retrieve the mock.
+ * Set the AuthMe plugin instance to a mock object. Use {@link AuthMe#getInstance()} to retrieve the mock.
+ *
+ * @return The generated mock for the AuthMe instance
*/
- public static void mockAuthMeInstance() {
+ public static AuthMe mockAuthMeInstance() {
AuthMe mock = Mockito.mock(AuthMe.class);
mockSingletonForClass(AuthMe.class, "plugin", mock);
+ return mock;
}
/**
- * Creates a mock Messages object for the instance returned from {@link Messages#getInstance()}.
+ * Create a mock Messages object for the instance returned from {@link Messages#getInstance()}.
*/
public static void mockMessagesInstance() {
Messages mock = Mockito.mock(Messages.class);
@@ -31,11 +35,39 @@ public final class AuthMeMockUtil {
}
/**
- * Sets a field of a class to the given mock.
+ * Set the given class' {@link Wrapper} field to a mock implementation.
*
- * @param clazz the class to modify
- * @param fieldName the field name
- * @param mock the mock to set for the given field
+ * @param clazz The class to modify
+ * @param fieldName The name of the field containing the Wrapper in the class
+ *
+ * @return The generated Wrapper mock
+ * @see WrapperMock
+ */
+ public static Wrapper insertMockWrapperInstance(Class> clazz, String fieldName) {
+ Wrapper wrapperMock = new WrapperMock();
+ mockSingletonForClass(clazz, fieldName, wrapperMock);
+ return wrapperMock;
+ }
+
+ public static Wrapper insertMockWrapperInstance(Class> clazz, String fieldName, AuthMe authMe) {
+ Wrapper wrapperMock = new WrapperMock(authMe);
+ mockSingletonForClass(clazz, fieldName, wrapperMock);
+ return wrapperMock;
+ }
+
+ // TODO ljacqu 20151123: Find the use cases for the WrapperMock and remove any of these
+ // methods that will end up unused
+ public static Wrapper insertMockWrapperInstance(Class> clazz, String fieldName, WrapperMock wrapperMock) {
+ mockSingletonForClass(clazz, fieldName, wrapperMock);
+ return wrapperMock;
+ }
+
+ /**
+ * Set a field of a class to the given mock.
+ *
+ * @param clazz The class to modify
+ * @param fieldName The field name
+ * @param mock The mock to set for the given field
*/
private static void mockSingletonForClass(Class> clazz, String fieldName, Object mock) {
try {
diff --git a/src/test/java/fr/xephi/authme/WrapperMock.java b/src/test/java/fr/xephi/authme/WrapperMock.java
new file mode 100644
index 000000000..bfad67be5
--- /dev/null
+++ b/src/test/java/fr/xephi/authme/WrapperMock.java
@@ -0,0 +1,54 @@
+package fr.xephi.authme;
+
+import fr.xephi.authme.util.Wrapper;
+import org.bukkit.Server;
+import org.mockito.Mockito;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * Class returning mocks for all calls in {@link Wrapper}.
+ * This class keeps track of its mocks and will always return
+ * the same one for each type.
+ */
+public class WrapperMock extends Wrapper {
+
+ private static Map, Object> mocks = new HashMap<>();
+
+ public WrapperMock() {
+ this((AuthMe) getMock(AuthMe.class));
+ }
+
+ public WrapperMock(AuthMe authMe) {
+ super(authMe);
+ }
+
+ @Override
+ public Logger getLogger() {
+ return getMock(Logger.class);
+ }
+
+ @Override
+ public Server getServer() {
+ return getMock(Server.class);
+ }
+
+ @Override
+ public AuthMe getAuthMe() {
+ return getMock(AuthMe.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static T getMock(Class> clazz) {
+ Object o = mocks.get(clazz);
+ if (o == null) {
+ o = Mockito.mock(clazz);
+ mocks.put(clazz, o);
+ }
+ return (T) o;
+ }
+
+
+}
diff --git a/src/test/java/fr/xephi/authme/settings/MessagesTest.java b/src/test/java/fr/xephi/authme/settings/MessagesTest.java
new file mode 100644
index 000000000..3d4f138ec
--- /dev/null
+++ b/src/test/java/fr/xephi/authme/settings/MessagesTest.java
@@ -0,0 +1,28 @@
+package fr.xephi.authme.settings;
+
+import fr.xephi.authme.AuthMe;
+import fr.xephi.authme.AuthMeMockUtil;
+import fr.xephi.authme.ConsoleLogger;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+
+/**
+ * Test for {@link Messages}.
+ */
+public class MessagesTest {
+
+ @Before
+ public void setUpMessages() {
+ AuthMe authMe = AuthMeMockUtil.mockAuthMeInstance();
+ AuthMeMockUtil.insertMockWrapperInstance(ConsoleLogger.class, "wrapper", authMe);
+ File file = new File("messages_test.yml");
+ Messages messages = new Messages(file, "en");
+ }
+
+ @Test
+ public void shouldLoadMessages() {
+
+ }
+}
diff --git a/src/test/java/fr/xephi/authme/util/UtilsTest.java b/src/test/java/fr/xephi/authme/util/UtilsTest.java
index d095746b3..97b64184c 100644
--- a/src/test/java/fr/xephi/authme/util/UtilsTest.java
+++ b/src/test/java/fr/xephi/authme/util/UtilsTest.java
@@ -2,6 +2,7 @@ package fr.xephi.authme.util;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.AuthMeMockUtil;
+import fr.xephi.authme.WrapperMock;
import fr.xephi.authme.permission.PermissionsManager;
import org.bukkit.Server;
import org.bukkit.entity.Player;
@@ -9,6 +10,7 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import java.lang.reflect.Field;
@@ -23,26 +25,32 @@ import static org.mockito.Mockito.when;
/**
* Test for the {@link Utils} class.
*/
+@Ignore
+// TODO ljacqu 20151123: Fix test setup
public class UtilsTest {
private AuthMe authMeMock;
private PermissionsManager permissionsManagerMock;
+ private Wrapper wrapperMock;
@Before
public void setUpMocks() {
- AuthMeMockUtil.mockAuthMeInstance();
- authMeMock = AuthMe.getInstance();
+ authMeMock = AuthMeMockUtil.mockAuthMeInstance();
- permissionsManagerMock = mock(PermissionsManager.class);
- when(authMeMock.getPermissionsManager()).thenReturn(permissionsManagerMock);
-
- Server serverMock = mock(Server.class);
- when(authMeMock.getGameServer()).thenReturn(serverMock);
+ // We need to create the Wrapper mock before injecting it into Utils because it runs a lot of code in
+ // a static block which needs the proper mocks to be set up.
+ wrapperMock = new WrapperMock(authMeMock);
+ Server serverMock = wrapperMock.getServer();
BukkitScheduler schedulerMock = mock(BukkitScheduler.class);
when(serverMock.getScheduler()).thenReturn(schedulerMock);
when(schedulerMock.runTaskAsynchronously(any(Plugin.class), any(Runnable.class)))
- .thenReturn(mock(BukkitTask.class));
+ .thenReturn(mock(BukkitTask.class));
+
+ AuthMeMockUtil.insertMockWrapperInstance(Utils.class, "wrapper", (WrapperMock) wrapperMock);
+
+ permissionsManagerMock = mock(PermissionsManager.class);
+ when(authMeMock.getPermissionsManager()).thenReturn(permissionsManagerMock);
}
// TODO ljacques 20151122: The tests for Utils.forceGM somehow can't be set up with the mocks correctly
diff --git a/src/test/resources/messages_test.yml b/src/test/resources/messages_test.yml
new file mode 100644
index 000000000..16218f329
--- /dev/null
+++ b/src/test/resources/messages_test.yml
@@ -0,0 +1,58 @@
+unknown_user: '&cCan''t find the requested user in the database!'
+unsafe_spawn: '&cYour quit location was unsafe, you have been teleported to the world''s spawnpoint.'
+not_logged_in: '&cYou''re not logged in!'
+reg_voluntarily: 'You can register yourself to the server with the command "/register "'
+usage_log: '&cUsage: /login '
+wrong_pwd: '&cWrong password!'
+unregistered: '&cSuccessfully unregistered!'
+reg_disabled: '&cIn-game registration is disabled!'
+valid_session: '&2Logged-in due to Session Reconnection.'
+login: '&2Successful login!'
+vb_nonActiv: '&cYour account isn''t activated yet, please check your emails!'
+user_regged: '&cYou already have registered this username!'
+usage_reg: '&cUsage: /register '
+max_reg: '&cYou have exceeded the maximum number of registrations for your connection!'
+no_perm: '&4You don''t have the permission to perform this action!'
+error: '&4An unexpected error occurred, please contact an Administrator!'
+login_msg: '&cPlease, login with the command "/login "'
+reg_msg: '&3Please, register to the server with the command "/register "'
+reg_email_msg: '&3Please, register to the server with the command "/register "'
+usage_unreg: '&cUsage: /unregister '
+pwd_changed: '&2Password changed successfully!'
+user_unknown: '&cThis user isn''t registered!'
+password_error: '&cPasswords didn''t match, check them again!'
+password_error_nick: '&cYou can''t use your name as password, please choose another one...'
+password_error_unsafe: '&cThe chosen password isn''t safe, please choose another one...'
+invalid_session: '&cYour IP has been changed and your session data has expired!'
+reg_only: '&4Only registered users can join the server! Please visit http://example.com to register yourself!'
+logged_in: '&cYou''re already logged in!'
+logout: '&2Logged-out successfully!'
+same_nick: '&4The same username is already playing on the server!'
+registered: '&2Successfully registered!'
+pass_len: '&cYour password is too short or too long! Please try with another one!'
+reload: '&2Configuration and database have been reloaded correctly!'
+timeout: '&4Login timeout exceeded, you have been kicked from the server, please try again!'
+usage_changepassword: '&cUsage: /changepassword '
+name_len: '&4Your username is either too short or too long!'
+regex: '&4Your username contains illegal characters. Allowed chars: REG_EX'
+add_email: '&3Please add your email to your account with the command "/email add "'
+recovery_email: '&3Forgot your password? Please use the command "/email recovery "'
+usage_captcha: '&3To login you have to solve a captcha code, please use the command "/captcha "'
+wrong_captcha: '&cWrong Captcha, please type "/captcha THE_CAPTCHA" into the chat!'
+valid_captcha: '&2Captcha code solved correctly!'
+kick_forvip: '&3A VIP Player has joined the server when it was full!'
+kick_fullserver: '&4The server is full, try again later!'
+usage_email_add: '&cUsage: /email add '
+usage_email_change: '&cUsage: /email change '
+usage_email_recovery: '&cUsage: /email recovery '
+new_email_invalid: '&cInvalid New Email, try again!'
+old_email_invalid: '&cInvalid Old Email, try again!'
+email_invalid: '&cInvalid Email address, try again!'
+email_added: '&2Email address successfully added to your account!'
+email_confirm: '&cPlease confirm your email address!'
+email_changed: '&2Email address changed correctly!'
+email_send: '&2Recovery email sent correctly! Check your email inbox!'
+email_exists: '&cA recovery email was already sent! You can discart it and send a new one using the command below:'
+country_banned: '&4Your country is banned from this server!'
+antibot_auto_enabled: '&4[AntiBotService] AntiBot enabled due to the huge number of connections!'
+antibot_auto_disabled: '&2[AntiBotService] AntiBot disabled disabled after %m minutes!'