#1255 Extract forum-specific data source actions into separate extension classes

This commit is contained in:
ljacqu
2017-07-23 14:01:35 +02:00
parent 870810a230
commit cbc794ba20
14 changed files with 589 additions and 420 deletions
@@ -1,16 +1,13 @@
package fr.xephi.authme.datasource;
import ch.jalu.configme.properties.Property;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -19,7 +16,6 @@ import org.junit.runners.Parameterized;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
@@ -64,13 +60,6 @@ public abstract class AbstractResourceClosingTest {
/** Collection of values to use to call methods with the parameters they expect. */
private static final Map<Class<?>, Object> PARAM_VALUES = getDefaultParameters();
/**
* Custom list of hash algorithms to use to test a method. By default we define {@link HashAlgorithm#XFBCRYPT} as
* algorithms we use as a lot of methods execute additional statements in {@link MySQL}. If other algorithms
* have custom behaviors, they can be supplied in this map so it will be tested as well.
*/
private static final Map<String, HashAlgorithm[]> CUSTOM_ALGORITHMS = getCustomAlgorithmList();
/** Mock of a settings instance. */
private static Settings settings;
@@ -84,23 +73,21 @@ public abstract class AbstractResourceClosingTest {
private List<AutoCloseable> closeables = new ArrayList<>();
/**
* Constructor for the test instance verifying the given method with the given hash algorithm.
* Constructor for the test instance verifying the given method.
*
* @param method The DataSource method to test
* @param name The name of the method
* @param algorithm The hash algorithm to use
*/
public AbstractResourceClosingTest(Method method, String name, HashAlgorithm algorithm) {
public AbstractResourceClosingTest(Method method, String name) {
// Note ljacqu 20160227: The name parameter is necessary as we pass it from the @Parameters method;
// we use the method name in the annotation to name the test sensibly
this.method = method;
given(settings.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(algorithm);
}
/** Initialize the settings mock and makes it return the default of any given property by default. */
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings("unchecked")
@BeforeClass
public static void initializeSettings() throws IOException, ClassNotFoundException {
public static void initializeSettings() {
settings = mock(Settings.class);
given(settings.getProperty(any(Property.class))).willAnswer(new Answer() {
@Override
@@ -129,24 +116,16 @@ public abstract class AbstractResourceClosingTest {
}
/**
* Initialization method -- provides the parameters to run the test with by scanning all DataSource
* methods. By default, we run one test per method with the default hash algorithm, XFBCRYPT.
* If the map of custom algorithms has an entry for the method name, we add an entry for each algorithm
* supplied by the map.
* Initialization method -- provides the parameters to run the test with by scanning all DataSource methods.
*
* @return Test parameters
*/
@Parameterized.Parameters(name = "{1}({2})")
@Parameterized.Parameters(name = "{1}")
public static Collection<Object[]> data() {
List<Method> methods = getDataSourceMethods();
List<Object[]> data = new ArrayList<>();
// Use XFBCRYPT if nothing else specified as there is a lot of specific behavior to this hash algorithm in MySQL
final HashAlgorithm[] defaultAlgorithm = new HashAlgorithm[]{HashAlgorithm.XFBCRYPT};
for (Method method : methods) {
HashAlgorithm[] algorithms = MoreObjects.firstNonNull(CUSTOM_ALGORITHMS.get(method.getName()), defaultAlgorithm);
for (HashAlgorithm algorithm : algorithms) {
data.add(new Object[]{method, method.getName(), algorithm});
}
data.add(new Object[]{method, method.getName()});
}
return data;
}
@@ -247,20 +226,6 @@ public abstract class AbstractResourceClosingTest {
.build();
}
/**
* Return the custom list of hash algorithms to test a method with to execute code specific to
* one hash algorithm. By default, XFBCRYPT is used. Only MySQL has code specific to algorithms
* but for technical reasons the custom list will be used for all tested classes.
*
* @return List of custom algorithms by method
*/
private static Map<String, HashAlgorithm[]> getCustomAlgorithmList() {
// We use XFBCRYPT as default encryption method so we don't have to list many of the special cases for it
return ImmutableMap.<String, HashAlgorithm[]>builder()
.put("saveAuth", new HashAlgorithm[]{HashAlgorithm.PHPBB, HashAlgorithm.WORDPRESS})
.build();
}
// ---------------------
// Mock initialization
// ---------------------
@@ -4,6 +4,8 @@ import ch.jalu.configme.properties.Property;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.DatabaseSettings;
import org.junit.After;
@@ -30,6 +32,8 @@ public class MySqlIntegrationTest extends AbstractDataSourceIntegrationTest {
/** Mock of a settings instance. */
private static Settings settings;
/** Mock of extensions factory. */
private static MySqlExtensionsFactory extensionsFactory;
/** SQL statement to execute before running a test. */
private static String sqlInitialize;
/** Connection to the H2 test database. */
@@ -51,6 +55,8 @@ public class MySqlIntegrationTest extends AbstractDataSourceIntegrationTest {
return ((Property) invocation.getArguments()[0]).getDefaultValue();
}
});
extensionsFactory = mock(MySqlExtensionsFactory.class);
when(extensionsFactory.buildExtension(any(Columns.class))).thenReturn(mock(MySqlExtension.class));
set(DatabaseSettings.MYSQL_DATABASE, "h2_test");
set(DatabaseSettings.MYSQL_TABLE, "authme");
TestHelper.setRealLogger();
@@ -85,7 +91,7 @@ public class MySqlIntegrationTest extends AbstractDataSourceIntegrationTest {
@Override
protected DataSource getDataSource(String saltColumn) {
when(settings.getProperty(DatabaseSettings.MYSQL_COL_SALT)).thenReturn(saltColumn);
return new MySQL(settings, hikariSource);
return new MySQL(settings, hikariSource, extensionsFactory);
}
private static <T> void set(Property<T> property, T value) {
@@ -1,12 +1,14 @@
package fr.xephi.authme.datasource;
import com.zaxxer.hikari.HikariDataSource;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
import fr.xephi.authme.settings.Settings;
import java.lang.reflect.Method;
import java.sql.Connection;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
@@ -15,15 +17,17 @@ import static org.mockito.Mockito.mock;
*/
public class MySqlResourceClosingTest extends AbstractResourceClosingTest {
public MySqlResourceClosingTest(Method method, String name, HashAlgorithm algorithm) {
super(method, name, algorithm);
public MySqlResourceClosingTest(Method method, String name) {
super(method, name);
}
@Override
protected DataSource createDataSource(Settings settings, Connection connection) throws Exception {
HikariDataSource hikariDataSource = mock(HikariDataSource.class);
given(hikariDataSource.getConnection()).willReturn(connection);
return new MySQL(settings, hikariDataSource);
MySqlExtensionsFactory extensionsFactory = mock(MySqlExtensionsFactory.class);
given(extensionsFactory.buildExtension(any(Columns.class))).willReturn(mock(MySqlExtension.class));
return new MySQL(settings, hikariDataSource, extensionsFactory);
}
}
@@ -1,6 +1,5 @@
package fr.xephi.authme.datasource;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.Settings;
import java.lang.reflect.Method;
@@ -11,8 +10,8 @@ import java.sql.Connection;
*/
public class SQLiteResourceClosingTest extends AbstractResourceClosingTest {
public SQLiteResourceClosingTest(Method method, String name, HashAlgorithm algorithm) {
super(method, name, algorithm);
public SQLiteResourceClosingTest(Method method, String name) {
super(method, name);
}
@Override