[Merge] Version 4.9.3 (#1141)

PR for version 4.9.3
This commit is contained in:
Risto Lahtela 2019-08-12 16:12:13 +03:00 committed by GitHub
commit b94189a60e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 454 additions and 449 deletions

3
Jenkinsfile vendored
View File

@ -6,9 +6,11 @@ pipeline {
steps {
dir("Plan") {
script {
sh 'rm -rf builds'
sh './gradlew clean shadowJar --parallel'
}
}
archiveArtifacts artifacts: 'Plan/builds/*.jar', fingerprint: false
}
}
stage('Tests') {
@ -50,6 +52,7 @@ pipeline {
dir("Plan") {
script {
sh './gradlew clean --parallel'
sh 'rm -rf builds'
}
}
}

View File

@ -68,8 +68,13 @@ public final class ExtensionExtractor {
}
}
private <T extends Annotation> Optional<T> getClassAnnotation(Class<T> ofClass) {
return Optional.ofNullable(extension.getClass().getAnnotation(ofClass));
private static <V extends DataExtension, T extends Annotation> Optional<T> getClassAnnotation(Class<V> from, Class<T> ofClass) {
return Optional.ofNullable(from.getAnnotation(ofClass));
}
public static <T extends DataExtension> String getPluginName(Class<T> extensionClass) {
return getClassAnnotation(extensionClass, PluginInfo.class).map(PluginInfo::name)
.orElseThrow(() -> new IllegalArgumentException("Given class had no PluginInfo annotation"));
}
private Method[] getMethods() {
@ -282,8 +287,13 @@ public final class ExtensionExtractor {
}
}
private <T extends Annotation> Optional<T> getClassAnnotation(Class<T> ofClass) {
return getClassAnnotation(extension.getClass(), ofClass);
}
private void extractPluginInfo() {
pluginInfo = getClassAnnotation(PluginInfo.class).orElseThrow(() -> new IllegalArgumentException("Given class had no PluginInfo annotation"));
pluginInfo = getClassAnnotation(PluginInfo.class)
.orElseThrow(() -> new IllegalArgumentException("Given class had no PluginInfo annotation"));
if (pluginInfo.name().length() > 50) {
warnings.add(extensionName + " PluginInfo 'name' was over 50 characters.");

View File

@ -22,7 +22,7 @@ allprojects {
wrapper.gradleVersion = "5.5.1"
group "com.djrapitops"
version "4.9.2"
version "4.9.3"
test {
useJUnitPlatform()
@ -74,7 +74,7 @@ subprojects {
ext.h2Version = "1.4.199"
ext.mysqlVersion = "8.0.17"
ext.hikariVersion = "3.3.1"
ext.slf4jVersion = "1.7.27"
ext.slf4jVersion = "1.7.28"
ext.geoIpVersion = "2.12.0"
ext.guavaVersion = "28.0-jre"
ext.bstatsVersion = "1.4"
@ -116,7 +116,6 @@ subprojects {
// Test Tooling Dependencies
testCompile "org.junit.jupiter:junit-jupiter-engine:5.5.1" // JUnit 5
testCompile "org.junit.platform:junit-platform-runner:1.5.1" // JUnit 4 runner for JUnit 5 tests
testCompile "org.junit.vintage:junit-vintage-engine:5.5.1" // JUnit 4 compatibility for JUnit 5
testCompile "org.junit.jupiter:junit-jupiter-params:5.5.1" // JUnit 5, parameterized tests
testCompile "org.mockito:mockito-core:3.0.0" // Mockito Core
testCompile "org.mockito:mockito-junit-jupiter:3.0.0" // Mockito JUnit 5 Extension

View File

@ -25,49 +25,42 @@ import com.djrapitops.plan.system.settings.ConfigSettingKeyTest;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.WebserverSettings;
import com.djrapitops.plan.system.settings.paths.key.Setting;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import rules.BukkitComponentMocker;
import rules.ComponentMocker;
import utilities.OptionalAssert;
import utilities.RandomData;
import utilities.mocks.BukkitMockComponent;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Optional;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test for Bukkit PlanSystem.
*
* @author Rsl1122
*/
@RunWith(MockitoJUnitRunner.Silent.class)
@RunWith(JUnitPlatform.class)
public class BukkitSystemTest {
@ClassRule
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
@Rule
public ComponentMocker component = new BukkitComponentMocker(temporaryFolder);
private final int TEST_PORT_NUMBER = RandomData.randomInt(9005, 9500);
private PlanSystem system;
@Before
public void prepareSystem() {
system = component.getPlanSystem();
@BeforeEach
void prepareSystem(@TempDir Path temp) throws Exception {
system = new BukkitMockComponent(temp).getPlanSystem();
system.getConfigSystem().getConfig()
.set(WebserverSettings.PORT, TEST_PORT_NUMBER);
}
@Test
public void bukkitSystemEnables() throws EnableException {
void bukkitSystemEnables() throws EnableException {
try {
system.enable();
assertTrue(system.isEnabled());
@ -77,7 +70,7 @@ public class BukkitSystemTest {
}
@Test
public void correctWebAddressInDatabaseAfterEnable() throws EnableException {
void correctWebAddressInDatabaseAfterEnable() throws EnableException {
try {
system.enable();
Database database = system.getDatabaseSystem().getDatabase();
@ -92,7 +85,7 @@ public class BukkitSystemTest {
}
@Test
public void bukkitSystemHasDefaultConfigValuesAfterEnable() throws EnableException, IllegalAccessException {
void bukkitSystemHasDefaultConfigValuesAfterEnable() throws EnableException, IllegalAccessException {
try {
system.enable();
PlanConfig config = system.getConfigSystem().getConfig();

View File

@ -23,9 +23,13 @@ import com.djrapitops.plugin.logging.console.TestPluginLogger;
import com.djrapitops.plugin.logging.error.ConsoleErrorLogger;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import utilities.TestConstants;
import java.util.concurrent.TimeUnit;
@ -37,20 +41,33 @@ import static org.mockito.Mockito.*;
*
* @author Rsl1122
*/
@RunWith(JUnitPlatform.class)
@ExtendWith(MockitoExtension.class)
public class AFKListenerTest {
private AFKListener underTest;
private static AFKListener underTest;
@Before
public void setUp() {
@BeforeAll
static void setUp() {
PlanConfig config = Mockito.mock(PlanConfig.class);
when(config.get(TimeSettings.AFK_THRESHOLD)).thenReturn(TimeUnit.MINUTES.toMillis(3));
underTest = new AFKListener(config, new ConsoleErrorLogger(new TestPluginLogger()));
}
@Test
public void afkPermissionIsNotCalledMoreThanOnce() {
Player player = mockPlayer();
void afkPermissionIsNotCalledMoreThanOnceWhenIgnored() {
Player player = mockPlayerWithPermissions();
PlayerMoveEvent event = mockMoveEvent(player);
underTest.onMove(event);
underTest.onMove(event);
verify(player, times(1)).hasPermission(anyString());
}
@Test
void afkPermissionIsNotCalledMoreThanOnceWhenNotIgnored() {
Player player = mockPlayerWithoutPermissions();
PlayerMoveEvent event = mockMoveEvent(player);
underTest.onMove(event);
@ -65,11 +82,18 @@ public class AFKListenerTest {
return event;
}
private Player mockPlayer() {
private Player mockPlayerWithPermissions() {
Player player = Mockito.mock(Player.class);
when(player.getUniqueId()).thenReturn(TestConstants.PLAYER_ONE_UUID);
when(player.hasPermission(anyString())).thenReturn(true);
return player;
}
private Player mockPlayerWithoutPermissions() {
Player player = Mockito.mock(Player.class);
when(player.getUniqueId()).thenReturn(TestConstants.PLAYER_TWO_UUID);
when(player.hasPermission(anyString())).thenReturn(false);
return player;
}
}

View File

@ -14,44 +14,47 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package rules;
package utilities.mocks;
import com.djrapitops.plan.DaggerPlanBukkitComponent;
import com.djrapitops.plan.Plan;
import com.djrapitops.plan.PlanBukkitComponent;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.system.PlanSystem;
import org.junit.rules.ExternalResource;
import org.junit.rules.TemporaryFolder;
import utilities.mocks.PlanBukkitMocker;
public class BukkitComponentMocker extends ExternalResource implements ComponentMocker {
import java.nio.file.Path;
private final TemporaryFolder testFolder;
/**
* Test utility for creating a dagger PlanComponent using a mocked Plan.
*
* @author Rsl1122
*/
public class BukkitMockComponent {
private final Path tempDir;
private Plan planMock;
private PlanBukkitComponent component;
public BukkitComponentMocker(TemporaryFolder testFolder) {
this.testFolder = testFolder;
public BukkitMockComponent(Path tempDir) {
this.tempDir = tempDir;
}
@Override
protected void before() throws Throwable {
PlanBukkitMocker mocker = PlanBukkitMocker.setUp()
.withDataFolder(testFolder.newFolder())
.withPluginDescription()
.withResourceFetchingFromJar()
.withServer();
planMock = mocker.getPlanMock();
component = DaggerPlanBukkitComponent.builder().plan(planMock).build();
}
public PlanPlugin getPlanMock() {
public Plan getPlanMock() throws Exception {
if (planMock == null) {
planMock = PlanBukkitMocker.setUp()
.withDataFolder(tempDir.toFile())
.withPluginDescription()
.withResourceFetchingFromJar()
.withServer()
.getPlanMock();
}
return planMock;
}
public PlanSystem getPlanSystem() {
public PlanSystem getPlanSystem() throws Exception {
if (component == null) {
component = DaggerPlanBukkitComponent.builder().plan(getPlanMock()).build();
}
return component.system();
}
}
}

View File

@ -84,17 +84,12 @@ public class PlanBukkitMocker extends Mocker {
return this;
}
public PlanBukkitMocker withDataFolder(File tempFolder) {
PlanBukkitMocker withDataFolder(File tempFolder) {
doReturn(tempFolder).when(planMock).getDataFolder();
return this;
}
@Deprecated
public PlanBukkitMocker withLogging() {
return this;
}
public PlanBukkitMocker withPluginDescription() {
PlanBukkitMocker withPluginDescription() {
try {
File pluginYml = getFile("/plugin.yml");
PluginDescriptionFile description = new PluginDescriptionFile(new FileInputStream(pluginYml));
@ -105,12 +100,12 @@ public class PlanBukkitMocker extends Mocker {
return this;
}
public PlanBukkitMocker withResourceFetchingFromJar() throws IOException {
PlanBukkitMocker withResourceFetchingFromJar() throws IOException {
withPluginFiles();
return this;
}
public PlanBukkitMocker withServer() {
PlanBukkitMocker withServer() {
Server serverMock = Mockito.mock(Server.class);
doReturn("").when(serverMock).getIp();
doReturn("Bukkit").when(serverMock).getName();
@ -129,7 +124,7 @@ public class PlanBukkitMocker extends Mocker {
return this;
}
public Plan getPlanMock() {
Plan getPlanMock() {
return planMock;
}
}

View File

@ -21,45 +21,44 @@ import com.djrapitops.plan.db.SQLiteDB;
import com.djrapitops.plan.system.PlanSystem;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.DatabaseSettings;
import com.djrapitops.plan.system.settings.paths.ProxySettings;
import com.djrapitops.plan.system.settings.paths.WebserverSettings;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import rules.BungeeComponentMocker;
import rules.ComponentMocker;
import utilities.CIProperties;
import utilities.DBPreparer;
import utilities.RandomData;
import utilities.mocks.BungeeMockComponent;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
/**
* Test for Bungee PlanSystem.
*
* @author Rsl1122
*/
@RunWith(MockitoJUnitRunner.Silent.class)
@RunWith(JUnitPlatform.class)
public class BungeeSystemTest {
@ClassRule
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
private final int TEST_PORT_NUMBER = RandomData.randomInt(9005, 9500);
@Rule
public ComponentMocker component = new BungeeComponentMocker(temporaryFolder);
@Rule
public ExpectedException thrown = ExpectedException.none();
private BungeeMockComponent component;
private DBPreparer dbPreparer;
@BeforeEach
void prepareSystem(@TempDir Path temp) throws Exception {
component = new BungeeMockComponent(temp);
dbPreparer = new DBPreparer(component.getPlanSystem(), TEST_PORT_NUMBER);
}
@Test
public void bungeeEnables() throws Exception {
void bungeeEnables() throws Exception {
PlanSystem bungeeSystem = component.getPlanSystem();
try {
PlanConfig config = bungeeSystem.getConfigSystem().getConfig();
@ -79,56 +78,51 @@ public class BungeeSystemTest {
}
@Test
public void bungeeDoesNotEnableWithDefaultIP() throws Exception {
thrown.expect(EnableException.class);
thrown.expectMessage("IP setting still 0.0.0.0 - Configure AlternativeIP/IP that connects to the Proxy server.");
void bungeeDoesNotEnableWithDefaultIP() {
EnableException thrown = assertThrows(EnableException.class, () -> {
PlanSystem bungeeSystem = component.getPlanSystem();
try {
PlanConfig config = bungeeSystem.getConfigSystem().getConfig();
config.set(WebserverSettings.PORT, TEST_PORT_NUMBER);
config.set(ProxySettings.IP, "0.0.0.0");
PlanSystem bungeeSystem = component.getPlanSystem();
try {
PlanConfig config = bungeeSystem.getConfigSystem().getConfig();
config.set(WebserverSettings.PORT, TEST_PORT_NUMBER);
config.set(ProxySettings.IP, "0.0.0.0");
DBSystem dbSystem = bungeeSystem.getDatabaseSystem();
SQLiteDB db = dbSystem.getSqLiteFactory().usingDefaultFile();
db.setTransactionExecutorServiceProvider(MoreExecutors::newDirectExecutorService);
dbSystem.setActiveDatabase(db);
DBSystem dbSystem = bungeeSystem.getDatabaseSystem();
SQLiteDB db = dbSystem.getSqLiteFactory().usingDefaultFile();
db.setTransactionExecutorServiceProvider(MoreExecutors::newDirectExecutorService);
dbSystem.setActiveDatabase(db);
bungeeSystem.enable(); // Throws EnableException
} finally {
bungeeSystem.disable();
}
});
bungeeSystem.enable(); // Throws EnableException
} finally {
bungeeSystem.disable();
}
assertEquals("IP setting still 0.0.0.0 - Configure AlternativeIP/IP that connects to the Proxy server.", thrown.getMessage());
}
@Test
public void testEnableNoMySQL() throws EnableException {
thrown.expect(EnableException.class);
void testEnableNoMySQL() {
assertThrows(EnableException.class, () -> {
PlanSystem bungeeSystem = component.getPlanSystem();
try {
PlanConfig config = bungeeSystem.getConfigSystem().getConfig();
config.set(WebserverSettings.PORT, TEST_PORT_NUMBER);
config.set(ProxySettings.IP, "8.8.8.8");
PlanSystem bungeeSystem = component.getPlanSystem();
try {
PlanConfig config = bungeeSystem.getConfigSystem().getConfig();
config.set(WebserverSettings.PORT, TEST_PORT_NUMBER);
config.set(ProxySettings.IP, "8.8.8.8");
bungeeSystem.enable(); // Throws EnableException
} finally {
bungeeSystem.disable();
}
bungeeSystem.enable(); // Throws EnableException
} finally {
bungeeSystem.disable();
}
});
}
@Test
public void testEnableWithMySQL() throws EnableException {
boolean isCI = Boolean.parseBoolean(System.getenv(CIProperties.IS_CI_SERVICE));
assumeTrue(isCI);
void testEnableWithMySQL() throws Exception {
PlanSystem bungeeSystem = component.getPlanSystem();
try {
PlanConfig config = bungeeSystem.getConfigSystem().getConfig();
config.set(DatabaseSettings.MYSQL_DATABASE, "Plan");
config.set(DatabaseSettings.MYSQL_USER, "travis");
config.set(DatabaseSettings.MYSQL_PASS, "");
config.set(DatabaseSettings.MYSQL_HOST, "127.0.0.1");
config.set(DatabaseSettings.TYPE, "MySQL");
// MySQL settings might not be available.
assumeTrue(dbPreparer.setUpMySQLSettings(config).isPresent());
config.set(WebserverSettings.PORT, TEST_PORT_NUMBER);
config.set(ProxySettings.IP, "8.8.8.8");

View File

@ -14,44 +14,47 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package rules;
package utilities.mocks;
import com.djrapitops.plan.DaggerPlanBungeeComponent;
import com.djrapitops.plan.PlanBungee;
import com.djrapitops.plan.PlanBungeeComponent;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.system.PlanSystem;
import org.junit.rules.ExternalResource;
import org.junit.rules.TemporaryFolder;
import utilities.mocks.PlanBungeeMocker;
public class BungeeComponentMocker extends ExternalResource implements ComponentMocker {
import java.nio.file.Path;
private final TemporaryFolder testFolder;
/**
* Test utility for creating a dagger PlanComponent using a mocked PlanBungee.
*
* @author Rsl1122
*/
public class BungeeMockComponent {
private final Path tempDir;
private PlanBungee planMock;
private PlanBungeeComponent component;
public BungeeComponentMocker(TemporaryFolder testFolder) {
this.testFolder = testFolder;
public BungeeMockComponent(Path tempDir) {
this.tempDir = tempDir;
}
@Override
protected void before() throws Throwable {
PlanBungeeMocker mocker = PlanBungeeMocker.setUp()
.withDataFolder(testFolder.newFolder())
.withPluginDescription()
.withResourceFetchingFromJar()
.withProxy();
planMock = mocker.getPlanMock();
component = DaggerPlanBungeeComponent.builder().plan(planMock).build();
}
public PlanPlugin getPlanMock() {
public PlanBungee getPlanMock() throws Exception {
if (planMock == null) {
planMock = PlanBungeeMocker.setUp()
.withDataFolder(tempDir.toFile())
.withResourceFetchingFromJar()
.withProxy()
.withPluginDescription()
.getPlanMock();
}
return planMock;
}
public PlanSystem getPlanSystem() {
public PlanSystem getPlanSystem() throws Exception {
if (component == null) {
component = DaggerPlanBungeeComponent.builder().plan(getPlanMock()).build();
}
return component.system();
}
}
}

View File

@ -83,23 +83,18 @@ public class PlanBungeeMocker extends Mocker {
return this;
}
public PlanBungeeMocker withDataFolder(File tempFolder) {
PlanBungeeMocker withDataFolder(File tempFolder) {
when(planMock.getDataFolder()).thenReturn(tempFolder);
return this;
}
public PlanBungeeMocker withResourceFetchingFromJar() throws Exception {
PlanBungeeMocker withResourceFetchingFromJar() throws Exception {
withPluginFiles();
return this;
}
@Deprecated
public PlanBungeeMocker withLogging() {
return this;
}
@SuppressWarnings("deprecation")
public PlanBungeeMocker withProxy() {
PlanBungeeMocker withProxy() {
ProxyServer proxyMock = Mockito.mock(ProxyServer.class);
doReturn("1.12.2").when(proxyMock).getVersion();
@ -117,7 +112,7 @@ public class PlanBungeeMocker extends Mocker {
return this;
}
public PlanBungeeMocker withPluginDescription() {
PlanBungeeMocker withPluginDescription() {
File pluginYml = getFile("/bungee.yml");
HashSet<String> empty = new HashSet<>();
PluginDescription pluginDescription = new PluginDescription("Plan", "", "9.9.9", "Rsl1122", empty, empty, pluginYml, "");
@ -125,7 +120,7 @@ public class PlanBungeeMocker extends Mocker {
return this;
}
public PlanBungee getPlanMock() {
PlanBungee getPlanMock() {
return planMock;
}
}

View File

@ -20,6 +20,8 @@ import com.djrapitops.plan.system.settings.config.ConfigNode;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
* Class responsible for generating and generating settings for PluginData
@ -74,4 +76,16 @@ public class PluginsConfigSection {
ConfigNode section = getPluginsSection();
return section.getBoolean(pluginName + ".Enabled");
}
public Set<String> getDisabled() {
ConfigNode section = getPluginsSection();
Set<String> disabledPlugins = new HashSet<>();
for (ConfigNode plugin : section.getChildren()) {
if (!plugin.getBoolean("Enabled")) {
disabledPlugins.add(plugin.getKey(false));
}
}
return disabledPlugins;
}
}

View File

@ -27,7 +27,6 @@ import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plugin.api.Check;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.logging.error.ErrorHandler;
@ -83,11 +82,9 @@ public class ExtensionServiceImplementation implements ExtensionService {
public void register() {
try {
extensionRegister.registerBuiltInExtensions();
if (Check.isBukkitAvailable()) extensionRegister.registerBukkitExtensions();
if (Check.isBungeeAvailable()) extensionRegister.registerBungeeExtensions();
extensionRegister.registerBuiltInExtensions(config.getPluginsConfigSection().getDisabled());
} catch (IllegalStateException failedToRegisterOne) {
logger.warn("One or more extensions failed to register:");
logger.warn("One or more extensions failed to register, see suppressed exceptions.");
errorHandler.log(L.WARN, this.getClass(), failedToRegisterOne);
}
}

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.query;
import com.djrapitops.plan.api.exceptions.database.DBOpException;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.QueryAPIExecutable;
import com.djrapitops.plan.db.access.QueryAPIQuery;
@ -23,6 +24,9 @@ import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.logging.error.ErrorHandler;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -39,6 +43,8 @@ public class QueryServiceImplementation implements QueryService {
private DBSystem dbSystem;
private ServerInfo serverInfo;
private final PluginLogger logger;
private final ErrorHandler errorHandler;
private Set<Consumer<UUID>> playerRemoveSubscribers;
private Set<VoidFunction> clearSubscribers;
@ -46,10 +52,14 @@ public class QueryServiceImplementation implements QueryService {
@Inject
public QueryServiceImplementation(
DBSystem dbSystem,
ServerInfo serverInfo
ServerInfo serverInfo,
PluginLogger logger,
ErrorHandler errorHandler
) {
this.dbSystem = dbSystem;
this.serverInfo = serverInfo;
this.logger = logger;
this.errorHandler = errorHandler;
playerRemoveSubscribers = new HashSet<>();
clearSubscribers = new HashSet<>();
@ -94,11 +104,25 @@ public class QueryServiceImplementation implements QueryService {
}
public void playerRemoved(UUID playerUUID) {
playerRemoveSubscribers.forEach(subscriber -> subscriber.accept(playerUUID));
playerRemoveSubscribers.forEach(subscriber -> {
try {
subscriber.accept(playerUUID);
} catch (DBOpException e) {
logger.warn("User of Query API (" + subscriber.getClass().getName() + ") ran into exception, failed safely:");
errorHandler.log(L.WARN, QueryService.class, e);
}
});
}
public void dataCleared() {
clearSubscribers.forEach(VoidFunction::apply);
clearSubscribers.forEach(function -> {
try {
function.apply();
} catch (DBOpException e) {
logger.warn("User of Query API (" + function.getClass().getName() + ") ran into exception, failed safely:");
errorHandler.log(L.WARN, QueryService.class, e);
}
});
}
@Override

View File

@ -349,6 +349,10 @@ public class ConfigNode {
return nodeOrder;
}
public Collection<ConfigNode> getChildren() {
return childNodes.values();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@ -1,7 +1,7 @@
name: Plan
author: Rsl1122
main: com.djrapitops.plan.PlanBungee
version: 4.9.2
version: 4.9.3
softdepend:
- AdvancedBan
- LiteBans

View File

@ -1,7 +1,7 @@
name: Plan
author: Rsl1122
main: com.djrapitops.plan.Plan
version: 4.9.2
version: 4.9.3
api-version: 1.13
softdepend:
- ASkyBlock

View File

@ -24,7 +24,7 @@ import utilities.TestConstants;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
abstract class DBPatchRegressionTest {
@ -91,6 +91,6 @@ abstract class DBPatchRegressionTest {
failed.add(patch.getClass().getSimpleName());
}
}
assertTrue("Patches " + failed + " were not applied properly.", failed.isEmpty());
assertTrue(failed.isEmpty(), "Patches " + failed + " were not applied properly.");
}
}

View File

@ -591,14 +591,16 @@ public interface DatabaseTest {
session.endSession(sessionStart + 22345L);
execute(DataStoreQueries.storeSession(session));
TestPluginLogger logger = new TestPluginLogger();
ConsoleErrorLogger errorHandler = new ConsoleErrorLogger(logger);
new DBCleanTask(
system().getConfigSystem().getConfig(),
new Locale(),
system().getDatabaseSystem(),
new QueryServiceImplementation(system().getDatabaseSystem(), system().getServerInfo()),
new QueryServiceImplementation(system().getDatabaseSystem(), system().getServerInfo(), logger, errorHandler),
system().getServerInfo(),
new TestPluginLogger(),
new ConsoleErrorLogger(new TestPluginLogger())
logger,
errorHandler
).cleanOldPlayers(db());
Collection<BaseUser> found = db().query(BaseUserQueries.fetchServerBaseUsers(serverUUID()));

View File

@ -31,7 +31,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Test for {@link PingStoreTransaction#getMeanValue()}.

View File

@ -26,7 +26,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Test class for {@link LocaleFileWriter}.

View File

@ -24,8 +24,8 @@ import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@RunWith(JUnitPlatform.class)
class VersionInfoLoaderTest {

View File

@ -24,7 +24,7 @@ import utilities.HTTPConnector;
import java.net.HttpURLConnection;
import java.net.URL;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
interface HttpsServerTest {
@ -36,7 +36,7 @@ interface HttpsServerTest {
@Test
default void webServerIsRunningHTTPS() {
assertTrue("WebServer is not using https", getWebServer().isUsingHTTPS());
assertTrue(getWebServer().isUsingHTTPS(), "WebServer is not using https");
}
/**

View File

@ -23,7 +23,6 @@ import com.djrapitops.plan.db.access.transactions.events.SessionEndTransaction;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.system.PlanSystem;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.locale.lang.ErrorPageLang;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.WebserverSettings;
import com.djrapitops.plan.system.webserver.cache.PageId;
@ -47,7 +46,7 @@ import java.nio.file.Path;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertFalse;
import static org.junit.jupiter.api.Assertions.assertFalse;
/**
* This test class is for catching any JavaScript errors.
@ -108,14 +107,18 @@ class JSErrorRegressionTest {
void playerPageDoesNotHaveJavascriptErrors(WebDriver driver) {
System.out.println("Testing Player Page");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/player/TestPlayer");
assertFalse(driver.getPageSource(), driver.getPageSource().contains("500 Internal Error occurred"));
assertNo500Error(driver);
}
private void assertNo500Error(WebDriver driver) {
assertFalse(driver.getPageSource().contains("500 Internal Error occurred"), driver.getPageSource());
}
@Test
void playerPageAccessibleViaUUID(WebDriver driver) {
System.out.println("Testing Player Page via UUID");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/player/" + TestConstants.PLAYER_ONE_UUID);
assertFalse(driver.getPageSource(), driver.getPageSource().contains(ErrorPageLang.NOT_PLAYED_404.getDefault()));
assertNo500Error(driver);
}
@Test
@ -123,7 +126,7 @@ class JSErrorRegressionTest {
System.out.println("Testing Server Page");
// Open the page that has refreshing info
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/server");
assertFalse(driver.getPageSource(), driver.getPageSource().contains("500 Internal Error occurred"));
assertNo500Error(driver);
// Wait until Plan caches analysis results
Awaitility.await()
@ -133,20 +136,20 @@ class JSErrorRegressionTest {
// Open the page with analysis stuff
SeleniumExtension.newTab(driver);
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/server");
assertFalse(driver.getPageSource(), driver.getPageSource().contains("500 Internal Error occurred"));
assertNo500Error(driver);
}
@Test
void playersPageDoesNotHaveJavascriptErrors(WebDriver driver) {
System.out.println("Testing Players Page");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/players");
assertFalse(driver.getPageSource(), driver.getPageSource().contains("500 Internal Error occurred"));
assertNo500Error(driver);
}
@Test
void debugPageDoesNotHaveJavascriptErrors(WebDriver driver) {
System.out.println("Testing Debug Page");
driver.get("http://localhost:" + TEST_PORT_NUMBER + "/debug");
assertFalse(driver.getPageSource(), driver.getPageSource().contains("500 Internal Error occurred"));
assertNo500Error(driver);
}
}

View File

@ -17,7 +17,7 @@
package extension;
import org.apache.commons.lang3.SystemUtils;
import org.junit.Assume;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.extension.*;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
@ -60,8 +60,8 @@ public class SeleniumExtension implements ParameterResolver, BeforeAllCallback,
@Override
public void beforeAll(ExtensionContext context) {
String driverLocation = getChromeDriverLocation();
Assume.assumeNotNull("rules.SeleniumDriver: Chrome driver location not specified for this OS type", driverLocation);
Assume.assumeTrue("rules.SeleniumDriver: Chrome driver not found at " + driverLocation, new File(driverLocation).exists());
Assumptions.assumeFalse(driverLocation == null, "rules.SeleniumDriver: Chrome driver location not specified for this OS type");
Assumptions.assumeTrue(new File(driverLocation).exists(), "rules.SeleniumDriver: Chrome driver not found at " + driverLocation);
System.setProperty("webdriver.chrome.driver", driverLocation);
driver = getChromeWebDriver();

View File

@ -1,27 +0,0 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package rules;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.system.PlanSystem;
import org.junit.rules.TestRule;
public interface ComponentMocker extends TestRule {
PlanPlugin getPlanMock();
PlanSystem getPlanSystem();
}

View File

@ -1,54 +0,0 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package rules;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.system.PlanSystem;
import org.junit.rules.ExternalResource;
import org.junit.rules.TemporaryFolder;
import utilities.dagger.DaggerPlanPluginComponent;
import utilities.dagger.PlanPluginComponent;
import utilities.mocks.PlanPluginMocker;
public class PluginComponentMocker extends ExternalResource implements ComponentMocker {
private final TemporaryFolder testFolder;
private PlanPlugin planMock;
private PlanPluginComponent component;
public PluginComponentMocker(TemporaryFolder testFolder) {
this.testFolder = testFolder;
}
@Override
protected void before() throws Throwable {
PlanPluginMocker mocker = PlanPluginMocker.setUp()
.withDataFolder(testFolder.newFolder())
.withResourceFetchingFromJar()
.withLogging();
planMock = mocker.getPlanMock();
component = DaggerPlanPluginComponent.builder().plan(planMock).build();
}
public PlanPlugin getPlanMock() {
return planMock;
}
public PlanSystem getPlanSystem() {
return component.system();
}
}

View File

@ -65,7 +65,7 @@ public class DBPreparer {
return db;
}
public Optional<Database> prepareMySQL() throws EnableException {
public Optional<String> setUpMySQLSettings(PlanConfig config) {
String database = System.getenv(CIProperties.MYSQL_DATABASE);
String user = System.getenv(CIProperties.MYSQL_USER);
String pass = System.getenv(CIProperties.MYSQL_PASS);
@ -80,22 +80,30 @@ public class DBPreparer {
String dbName = DBType.MYSQL.getName();
PlanConfig config = system.getConfigSystem().getConfig();
config.set(DatabaseSettings.MYSQL_DATABASE, formattedDatabase);
config.set(DatabaseSettings.MYSQL_USER, user);
config.set(DatabaseSettings.MYSQL_PASS, pass);
config.set(DatabaseSettings.MYSQL_HOST, "127.0.0.1");
config.set(DatabaseSettings.TYPE, dbName);
return Optional.of(formattedDatabase);
}
SQLDB mysql = prepareDBByName(dbName);
mysql.executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute("DROP DATABASE " + formattedDatabase);
execute("CREATE DATABASE " + formattedDatabase);
execute("USE " + formattedDatabase);
}
});
return Optional.of(mysql);
public Optional<Database> prepareMySQL() throws EnableException {
PlanConfig config = system.getConfigSystem().getConfig();
Optional<String> formattedDB = setUpMySQLSettings(config);
if (formattedDB.isPresent()) {
String formattedDatabase = formattedDB.get();
SQLDB mysql = prepareDBByName(DBType.MYSQL.getName());
mysql.executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute("DROP DATABASE " + formattedDatabase);
execute("CREATE DATABASE " + formattedDatabase);
execute("USE " + formattedDatabase);
}
});
return Optional.of(mysql);
}
return Optional.empty();
}
}

View File

@ -16,8 +16,6 @@
*/
package utilities;
import org.junit.rules.ExternalResource;
import javax.net.ssl.*;
import java.io.IOException;
import java.net.HttpURLConnection;
@ -25,7 +23,7 @@ import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
public class HTTPConnector extends ExternalResource {
public class HTTPConnector {
private static final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {

View File

@ -26,7 +26,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestResources {
@ -44,13 +44,7 @@ public class TestResources {
public static void copyResourceIntoFile(File toFile, String resourcePath) {
createEmptyFile(toFile);
writeResourceToFile(toFile, resourcePath);
assertTrue("Failed to copy resource: '" + resourcePath + "'", toFile.exists());
}
public static void copyTestResourceIntoFile(File toFile, InputStream testResource) {
createEmptyFile(toFile);
copyResourceToFile(toFile, testResource);
assertTrue("Failed to copy resource: '" + toFile.getAbsolutePath() + "'", toFile.exists());
assertTrue(toFile.exists(), () -> "Failed to copy resource: '" + resourcePath + "'");
}
private static void copyResourceToFile(File toFile, InputStream testResource) {

View File

@ -1,8 +1,8 @@
dependencies {
compile project(path: ":api")
compile 'com.djrapitops:Extension-AAC:4.0.5-R0.3'
compile 'com.djrapitops:Extension-AAC:4.0.11-R0.1'
compile 'com.djrapitops:Extension-AdvancedAchievements:1.1-R0.3'
compile 'com.djrapitops:Extension-AdvancedBan:2.1.5-R0.6'
compile 'com.djrapitops:Extension-AdvancedBan:2.1.5-R0.8'
compile 'com.djrapitops:Extension-ASkyBlock:3.0.9.4-R0.4'
compile 'com.djrapitops:Extension-BanManager:5.15.0-R0.5'
compile 'com.djrapitops:Extension-CoreProtect:2.16.0-R0.3'
@ -14,13 +14,13 @@ dependencies {
compile 'com.djrapitops:Extension-McMMO:2.1.44-R0.2'
compile 'com.djrapitops:Extension-MinigamesLib:1.14.17-R0.2'
compile 'com.djrapitops:Extension-Nucleus:1.9.2-R0.2'
compile 'com.djrapitops:Extension-nuVotifier:2.3.4-R0.2'
compile 'com.djrapitops:Extension-ProtocolSupport:4.29-R0.2'
compile 'com.djrapitops:Extension-nuVotifier:2.3.4-R0.3'
compile 'com.djrapitops:Extension-ProtocolSupport:4.29-R0.3'
compile 'com.djrapitops:Extension-RedProtect:7.5.6-R0.2'
compile 'com.djrapitops:Extension-Sponge-Economy:7.1.0-R0.3'
compile 'com.djrapitops:Extension-SuperbVote:0.5.4-R0.1'
compile 'com.djrapitops:Extension-Vault:1.7-R0.2'
compile 'com.djrapitops:Extension-ViaVersion:2.1.3-R0.3'
compile 'com.djrapitops:Extension-ViaVersion:2.1.3-R1.1'
}
shadowJar {

View File

@ -17,13 +17,17 @@
package com.djrapitops.plan.extension.implementation;
import com.djrapitops.extension.*;
import com.djrapitops.plan.extension.Caller;
import com.djrapitops.plan.extension.DataExtension;
import com.djrapitops.plan.extension.ExtensionService;
import com.djrapitops.plan.extension.extractor.ExtensionExtractor;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;
/**
* In charge of registering built in {@link com.djrapitops.plan.extension.DataExtension} implementations.
@ -34,72 +38,93 @@ import java.util.function.Supplier;
public class ExtensionRegister {
private IllegalStateException registerException;
private Set<String> disabledExtensions;
private ExtensionService extensionService;
@Inject
public ExtensionRegister() {
/* Required for dagger injection */
}
public void registerBuiltInExtensions() {
// No need to catch exceptions here,
// registerBuiltInExtensions method will not be called unless Plan has enabled properly
ExtensionService extensionService = ExtensionService.getInstance();
public void registerBuiltInExtensions(Set<String> disabledExtensions) {
this.disabledExtensions = disabledExtensions;
extensionService = ExtensionService.getInstance();
register(new AACExtensionFactory()::createExtension);
register(new AdvancedAchievementsExtensionFactory()::createExtension);
register(new AdvancedBanExtensionFactory()::createExtension);
register(new ASkyBlockExtensionFactory()::createExtension);
register(new BanManagerExtensionFactory()::createExtension);
register(new CoreProtectExtensionFactory()::createExtension);
register(new DiscordSRVExtensionFactory()::createExtension);
registerEssentialsExtension(extensionService);
register(new GriefPreventionExtensionFactory()::createExtension);
register(new GriefPreventionSpongeExtensionFactory()::createExtension);
register(new GriefPreventionPlusExtensionFactory()::createExtension);
register(new McMMOExtensionFactory()::createExtension);
registerMinigameLibExtensions(extensionService);
register(new NucleusExtensionFactory()::createExtension);
register(new NuVotifierExtensionFactory()::createExtension);
register(new ProtocolSupportExtensionFactory()::createExtension);
register(new RedProtectExtensionFactory()::createExtension);
register(new SpongeEconomyExtensionFactory()::createExtension);
register(new SuperbVoteExtensionFactory()::createExtension);
register(new VaultExtensionFactory()::createExtension);
register(new AACExtensionFactory(), AACExtensionFactory::createExtension);
register(new AdvancedAchievementsExtensionFactory(), AdvancedAchievementsExtensionFactory::createExtension);
register(new AdvancedBanExtensionFactory(), AdvancedBanExtensionFactory::createExtension, AdvancedBanExtensionFactory::registerListener);
register(new ASkyBlockExtensionFactory(), ASkyBlockExtensionFactory::createExtension);
register(new BanManagerExtensionFactory(), BanManagerExtensionFactory::createExtension);
register(new CoreProtectExtensionFactory(), CoreProtectExtensionFactory::createExtension);
register(new DiscordSRVExtensionFactory(), DiscordSRVExtensionFactory::createExtension);
register(new EssentialsExtensionFactory(), EssentialsExtensionFactory::createExtension, EssentialsExtensionFactory::registerUpdateListeners);
register(new GriefPreventionExtensionFactory(), GriefPreventionExtensionFactory::createExtension);
register(new GriefPreventionSpongeExtensionFactory(), GriefPreventionSpongeExtensionFactory::createExtension);
register(new GriefPreventionPlusExtensionFactory(), GriefPreventionPlusExtensionFactory::createExtension);
register(new McMMOExtensionFactory(), McMMOExtensionFactory::createExtension);
registerMinigameLibExtensions();
register(new NucleusExtensionFactory(), NucleusExtensionFactory::createExtension);
register(new NuVotifierExtensionFactory(), NuVotifierExtensionFactory::createExtension);
register(new ProtocolSupportExtensionFactory(), ProtocolSupportExtensionFactory::createExtension);
register(new RedProtectExtensionFactory(), RedProtectExtensionFactory::createExtension);
register(new SpongeEconomyExtensionFactory(), SpongeEconomyExtensionFactory::createExtension);
register(new SuperbVoteExtensionFactory(), SuperbVoteExtensionFactory::createExtension);
register(new VaultExtensionFactory(), VaultExtensionFactory::createExtension);
register(new ViaVersionExtensionFactory(), ViaVersionExtensionFactory::createExtension);
if (registerException != null) throw registerException;
}
public void registerBukkitExtensions() {
register(new ViaVersionBukkitExtensionFactory()::createExtension);
}
public void registerBungeeExtensions() {
register(new ViaVersionBungeeExtensionFactory()::createExtension);
}
private void registerEssentialsExtension(ExtensionService extensionService) {
EssentialsExtensionFactory essentials = new EssentialsExtensionFactory();
essentials.createExtension()
.flatMap(extensionService::register) // If the extension was registered this is present.
.ifPresent(essentials::registerUpdateListeners);
}
private void registerMinigameLibExtensions(ExtensionService extensionService) {
private void registerMinigameLibExtensions() {
for (DataExtension minigame : new MinigameLibExtensionFactory().createExtensions()) {
extensionService.register(minigame);
register(minigame);
}
}
private void register(Supplier<Optional<DataExtension>> extension) {
ExtensionService extensionService = ExtensionService.getInstance();
try {
extension.get().ifPresent(extensionService::register);
} catch (IllegalStateException e) {
if (registerException == null) {
registerException = e;
} else {
registerException.addSuppressed(e);
}
private void suppressException(Class factory, Throwable e) {
// Places all exceptions to one exception with plugin information so that they can be reported.
if (registerException == null) {
registerException = new IllegalStateException("One or more extensions failed to register:");
registerException.setStackTrace(new StackTraceElement[0]);
}
IllegalStateException info = new IllegalStateException(factory.getSimpleName() + " ran into exception when creating Extension", e);
info.setStackTrace(new StackTraceElement[0]);
registerException.addSuppressed(info);
}
private <T> void register(
T factory,
Function<T, Optional<DataExtension>> createExtension
) {
try {
// Creates the extension with factory and registers it
createExtension.apply(factory).flatMap(this::register);
} catch (IllegalStateException | NoClassDefFoundError | IncompatibleClassChangeError e) {
// Places all exceptions to one exception with plugin information so that they can be reported.
suppressException(factory.getClass(), e);
}
}
private <T> void register(
T factory,
Function<T, Optional<DataExtension>> createExtension,
BiConsumer<T, Caller> registerListener
) {
try {
// Creates the extension with factory and registers it, then registers listener
createExtension.apply(factory)
.flatMap(this::register)
.ifPresent(caller -> registerListener.accept(factory, caller));
} catch (IllegalStateException | NoClassDefFoundError | IncompatibleClassChangeError e) {
// Places all exceptions to one exception with plugin information so that they can be reported.
suppressException(factory.getClass(), e);
}
}
private Optional<Caller> register(DataExtension dataExtension) {
String extensionName = ExtensionExtractor.getPluginName(dataExtension.getClass());
if (disabledExtensions.contains(extensionName)) return Optional.empty();
return extensionService.register(dataExtension);
}
}

View File

@ -42,7 +42,7 @@ import java.io.InputStream;
@Plugin(
id = "plan",
name = "Plan",
version = "4.9.2",
version = "4.9.3",
description = "Player Analytics Plugin by Rsl1122",
authors = {"Rsl1122"},
dependencies = {

View File

@ -22,48 +22,41 @@ import com.djrapitops.plan.system.settings.ConfigSettingKeyTest;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.WebserverSettings;
import com.djrapitops.plan.system.settings.paths.key.Setting;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import rules.ComponentMocker;
import rules.SpongeComponentMocker;
import utilities.RandomData;
import utilities.mocks.SpongeMockComponent;
import java.nio.file.Path;
import java.util.Collection;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test for Sponge PlanSystem.
*
* @author Rsl1122
*/
@RunWith(MockitoJUnitRunner.Silent.class)
@RunWith(JUnitPlatform.class)
public class SpongeSystemTest {
@ClassRule
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
@Rule
public ComponentMocker component = new SpongeComponentMocker(temporaryFolder);
private final int TEST_PORT_NUMBER = RandomData.randomInt(9005, 9500);
private PlanSystem system;
@Before
public void prepareSpongeSystem() {
system = component.getPlanSystem();
@BeforeEach
void prepareSpongeSystem(@TempDir Path temp) throws Exception {
system = new SpongeMockComponent(temp).getPlanSystem();
system.getConfigSystem().getConfig()
.set(WebserverSettings.PORT, TEST_PORT_NUMBER);
}
@Test
public void spongeSystemEnables() throws EnableException {
void spongeSystemEnables() throws EnableException {
try {
system.enable();
assertTrue(system.isEnabled());
@ -73,7 +66,7 @@ public class SpongeSystemTest {
}
@Test
public void spongeSystemHasDefaultConfigValuesAfterEnable() throws EnableException, IllegalAccessException {
void spongeSystemHasDefaultConfigValuesAfterEnable() throws EnableException, IllegalAccessException {
try {
system.enable();
PlanConfig config = system.getConfigSystem().getConfig();

View File

@ -86,12 +86,12 @@ public class PlanSpongeMocker extends Mocker {
return this;
}
public PlanSpongeMocker withDataFolder(File tempFolder) {
PlanSpongeMocker withDataFolder(File tempFolder) {
when(planMock.getDataFolder()).thenReturn(tempFolder);
return this;
}
public PlanSpongeMocker withGame() {
PlanSpongeMocker withGame() {
Game game = Mockito.mock(Game.class);
Platform platform = mockPlatform();
@ -130,12 +130,12 @@ public class PlanSpongeMocker extends Mocker {
return server;
}
public PlanSpongeMocker withResourceFetchingFromJar() throws Exception {
PlanSpongeMocker withResourceFetchingFromJar() throws Exception {
withPluginFiles();
return this;
}
public PlanSponge getPlanMock() {
PlanSponge getPlanMock() {
return planMock;
}
}

View File

@ -14,44 +14,46 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package rules;
package utilities.mocks;
import com.djrapitops.plan.DaggerPlanSpongeComponent;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.PlanSponge;
import com.djrapitops.plan.PlanSpongeComponent;
import com.djrapitops.plan.system.PlanSystem;
import org.junit.rules.ExternalResource;
import org.junit.rules.TemporaryFolder;
import utilities.mocks.PlanSpongeMocker;
public class SpongeComponentMocker extends ExternalResource implements ComponentMocker {
import java.nio.file.Path;
private final TemporaryFolder testFolder;
/**
* Test utility for creating a dagger PlanComponent using a mocked PlanSponge.
*
* @author Rsl1122
*/
public class SpongeMockComponent {
private final Path tempDir;
private PlanSponge planMock;
private PlanSpongeComponent component;
public SpongeComponentMocker(TemporaryFolder testFolder) {
this.testFolder = testFolder;
public SpongeMockComponent(Path tempDir) {
this.tempDir = tempDir;
}
@Override
protected void before() throws Throwable {
PlanSpongeMocker mocker = PlanSpongeMocker.setUp()
.withDataFolder(testFolder.newFolder())
.withResourceFetchingFromJar()
.withGame();
planMock = mocker.getPlanMock();
component = DaggerPlanSpongeComponent.builder().plan(planMock).build();
}
public PlanPlugin getPlanMock() {
public PlanSponge getPlanMock() throws Exception {
if (planMock == null) {
planMock = PlanSpongeMocker.setUp()
.withDataFolder(tempDir.toFile())
.withResourceFetchingFromJar()
.withGame()
.getPlanMock();
}
return planMock;
}
public PlanSystem getPlanSystem() {
public PlanSystem getPlanSystem() throws Exception {
if (component == null) {
component = DaggerPlanSpongeComponent.builder().plan(getPlanMock()).build();
}
return component.system();
}
}
}

View File

@ -46,7 +46,7 @@ import java.nio.file.Path;
@Plugin(
id = "plan",
name = "Plan",
version = "4.9.2",
version = "4.9.3",
description = "Player Analytics Plugin by Rsl1122",
authors = {"Rsl1122"}
)

View File

@ -23,35 +23,31 @@ import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.ProxySettings;
import com.djrapitops.plan.system.settings.paths.WebserverSettings;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import rules.ComponentMocker;
import rules.VelocityComponentMocker;
import utilities.RandomData;
import utilities.mocks.VelocityMockComponent;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.Assert.assertTrue;
/**
* Test for Velocity PlanSystem.
*
* @author Rsl1122
*/
@RunWith(MockitoJUnitRunner.Silent.class)
@RunWith(JUnitPlatform.class)
public class VelocitySystemTest {
@ClassRule
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
@ClassRule
public static ComponentMocker component = new VelocityComponentMocker(temporaryFolder);
private final int TEST_PORT_NUMBER = RandomData.randomInt(9005, 9500);
@Test
public void velocityEnables() throws Exception {
PlanSystem velocitySystem = component.getPlanSystem();
void velocityEnables(@TempDir Path temp) throws Exception {
PlanSystem velocitySystem = new VelocityMockComponent(temp).getPlanSystem();
try {
PlanConfig config = velocitySystem.getConfigSystem().getConfig();
config.set(WebserverSettings.PORT, TEST_PORT_NUMBER);

View File

@ -19,16 +19,18 @@ package com.djrapitops.plan.system.tasks.velocity;
import com.djrapitops.plan.PlanVelocity;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import utilities.TestConstants;
import utilities.mocks.PlanVelocityMocker;
import java.util.Optional;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
/**
@ -36,13 +38,14 @@ import static org.mockito.Mockito.when;
*
* @author Rsl1122
*/
@RunWith(JUnitPlatform.class)
public class PingCountTimerVelocityTest {
private PlanVelocity plugin;
private Player player;
@Before
public void setUp() {
@BeforeEach
void setUp() {
PlanVelocityMocker mocker = PlanVelocityMocker.setUp()
.withProxy();
plugin = mocker.getPlanMock();
@ -56,7 +59,7 @@ public class PingCountTimerVelocityTest {
}
@Test
public void offlinePlayerIsRemovedFromPlayerHistory() {
void offlinePlayerIsRemovedFromPlayerHistory() {
PingCountTimerVelocity counter = new PingCountTimerVelocity(plugin, null, null, null, null);
assertTrue(counter.playerHistory.isEmpty());

View File

@ -14,42 +14,46 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package rules;
package utilities.mocks;
import com.djrapitops.plan.DaggerPlanVelocityComponent;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.PlanVelocity;
import com.djrapitops.plan.PlanVelocityComponent;
import com.djrapitops.plan.system.PlanSystem;
import org.junit.rules.ExternalResource;
import org.junit.rules.TemporaryFolder;
import utilities.mocks.PlanVelocityMocker;
public class VelocityComponentMocker extends ExternalResource implements ComponentMocker {
private final TemporaryFolder testFolder;
import java.nio.file.Path;
/**
* Test utility for creating a dagger PlanComponent using a mocked Plan.
*
* @author Rsl1122
*/
public class VelocityMockComponent {
private final Path tempDir;
private PlanVelocity planMock;
private PlanVelocityComponent component;
public VelocityComponentMocker(TemporaryFolder testFolder) {
this.testFolder = testFolder;
public VelocityMockComponent(Path tempDir) {
this.tempDir = tempDir;
}
@Override
protected void before() throws Throwable {
PlanVelocityMocker mocker = PlanVelocityMocker.setUp()
.withDataFolder(testFolder.newFolder())
.withResourceFetchingFromJar()
.withProxy();
planMock = mocker.getPlanMock();
component = DaggerPlanVelocityComponent.builder().plan(planMock).build();
}
public PlanPlugin getPlanMock() {
public PlanVelocity getPlanMock() throws Exception {
if (planMock == null) {
planMock = PlanVelocityMocker.setUp()
.withDataFolder(tempDir.toFile())
.withResourceFetchingFromJar()
.withProxy()
.getPlanMock();
}
return planMock;
}
public PlanSystem getPlanSystem() {
public PlanSystem getPlanSystem() throws Exception {
if (component == null) {
component = DaggerPlanVelocityComponent.builder().plan(getPlanMock()).build();
}
return component.system();
}
}
}

View File

@ -195,7 +195,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
<version>0.8.4</version>
</plugin>
</plugins>
</build>