From 7030e86496f102a38a991011f138d689d4e0b857 Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Sat, 15 Dec 2018 13:14:51 +0200 Subject: [PATCH] Test for default config value validity --- .../system/settings/ConfigSettingKeyTest.java | 143 ++++++++++++++++ .../src/test/java/utilities/FieldFetcher.java | 42 +++++ .../test/java/utilities/TestResources.java | 86 ++++++++++ .../resources/config/4.5.2-bungeeconfig.yml | 129 +++++++++++++++ .../test/resources/config/4.5.2-config.yml | 155 ++++++++++++++++++ Plan/pom.xml | 11 ++ 6 files changed, 566 insertions(+) create mode 100644 Plan/common/src/test/java/com/djrapitops/plan/system/settings/ConfigSettingKeyTest.java create mode 100644 Plan/common/src/test/java/utilities/FieldFetcher.java create mode 100644 Plan/common/src/test/java/utilities/TestResources.java create mode 100644 Plan/common/src/test/resources/config/4.5.2-bungeeconfig.yml create mode 100644 Plan/common/src/test/resources/config/4.5.2-config.yml diff --git a/Plan/common/src/test/java/com/djrapitops/plan/system/settings/ConfigSettingKeyTest.java b/Plan/common/src/test/java/com/djrapitops/plan/system/settings/ConfigSettingKeyTest.java new file mode 100644 index 0000000000..429b76eb1f --- /dev/null +++ b/Plan/common/src/test/java/com/djrapitops/plan/system/settings/ConfigSettingKeyTest.java @@ -0,0 +1,143 @@ +/* + * 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 . + */ +package com.djrapitops.plan.system.settings; + +import com.djrapitops.plan.system.settings.config.PlanConfig; +import com.djrapitops.plan.system.settings.paths.*; +import com.djrapitops.plan.system.settings.paths.key.Setting; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import utilities.FieldFetcher; +import utilities.TestResources; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Test to check that configs contain all values required to run the plugin. + * + * @author Rsl1122 + */ +public class ConfigSettingKeyTest { + + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Test + public void serverConfigHasValidDefaultValues() throws IOException, IllegalAccessException { + PlanConfig planConfig = createConfig("config.yml"); + Collection settings = getServerSettings(); + hasValidDefaultValuesForAllSettings(planConfig, settings); + } + + @Test + public void networkConfigHasValidDefaultValues() throws IOException, IllegalAccessException { + PlanConfig planConfig = createConfig("bungeeconfig.yml"); + Collection settings = getNetworkSettings(); + hasValidDefaultValuesForAllSettings(planConfig, settings); + } + + private void hasValidDefaultValuesForAllSettings(PlanConfig config, Iterable settings) { + List fails = new ArrayList<>(); + for (Setting setting : settings) { + checkSettingForFailures(config, setting).ifPresent(fails::add); + } + assertTrue(fails.isEmpty(), fails::toString); + } + + private Optional checkSettingForFailures(PlanConfig config, Setting setting) { + try { + if (!config.contains(setting.getPath())) { + return Optional.of("Did not contain " + setting.getPath()); + } else { + config.get(setting); + return Optional.empty(); + } + } catch (IllegalStateException validationFailed) { + return Optional.of(validationFailed.getMessage()); + } + } + + private Collection getServerSettings() throws IllegalAccessException { + List settings = new ArrayList<>(); + for (Class settingKeyClass : new Class[]{ + DatabaseSettings.class, + DataGatheringSettings.class, + DisplaySettings.class, + ExportSettings.class, + FormatSettings.class, + PluginDataSettings.class, + PluginSettings.class, + TimeSettings.class, + WebserverSettings.class + }) { + settings.addAll(FieldFetcher.getPublicStaticFields(settingKeyClass, Setting.class)); + } + return settings; + } + + private Collection getNetworkSettings() throws IllegalAccessException { + List settings = new ArrayList<>(); + for (Class settingKeyClass : new Class[]{ + DatabaseSettings.class, + DisplaySettings.class, + ExportSettings.class, + FormatSettings.class, + PluginSettings.class, + ProxySettings.class, + TimeSettings.class, + WebserverSettings.class + }) { + settings.addAll(FieldFetcher.getPublicStaticFields(settingKeyClass, Setting.class)); + } + settings.add(PluginDataSettings.PLUGIN_BUYCRAFT_SECRET); + + // Server settings contained in the key classes, remove + settings.remove(PluginSettings.SERVER_NAME); + settings.remove(PluginSettings.BUNGEE_COPY_CONFIG); + settings.remove(DatabaseSettings.TYPE); + settings.remove(DisplaySettings.PLAYERS_PER_SERVER_PAGE); + settings.remove(DisplaySettings.GRAPH_TPS_THRESHOLD_MED); + settings.remove(DisplaySettings.GRAPH_TPS_THRESHOLD_HIGH); + settings.remove(DisplaySettings.GRAPH_DISK_THRESHOLD_MED); + settings.remove(DisplaySettings.GRAPH_DISK_THRESHOLD_HIGH); + settings.remove(DisplaySettings.GRAPH_DISK_THRESHOLD_HIGH); + settings.remove(DisplaySettings.WORLD_ALIASES); + settings.remove(TimeSettings.ANALYSIS_REFRESH_PERIOD); + return settings; + } + + private PlanConfig createConfig(String copyDefaultSettingsFrom) throws IOException { + File configFile = temporaryFolder.newFile(); + TestResources.copyResourceIntoFile(configFile, "/" + copyDefaultSettingsFrom); + return createConfig(configFile); + } + + private PlanConfig createConfig(File configFile) throws IOException { + PlanConfig config = new PlanConfig(configFile, null, null); + config.save(); + return config; + } + +} \ No newline at end of file diff --git a/Plan/common/src/test/java/utilities/FieldFetcher.java b/Plan/common/src/test/java/utilities/FieldFetcher.java new file mode 100644 index 0000000000..38cb10ef78 --- /dev/null +++ b/Plan/common/src/test/java/utilities/FieldFetcher.java @@ -0,0 +1,42 @@ +/* + * 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 . + */ +package utilities; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +public class FieldFetcher { + + private FieldFetcher() { + /* static method class*/ + } + + public static List getPublicStaticFields(Class fromClass, Class ofType) throws IllegalAccessException { + List list = new ArrayList<>(); + for (Field field : fromClass.getDeclaredFields()) { + if (!Modifier.isPublic(field.getModifiers())) { + continue; + } + T key = (T) field.get(null); + list.add(key); + } + return list; + } + +} diff --git a/Plan/common/src/test/java/utilities/TestResources.java b/Plan/common/src/test/java/utilities/TestResources.java new file mode 100644 index 0000000000..be5444c109 --- /dev/null +++ b/Plan/common/src/test/java/utilities/TestResources.java @@ -0,0 +1,86 @@ +/* + * 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 . + */ +package utilities; + +import com.djrapitops.plan.PlanPlugin; + +import java.io.*; +import java.net.URISyntaxException; +import java.nio.file.Paths; + +public class TestResources { + + private TestResources() { + /* static method class */ + } + + public static File getTestResourceFile(String called, Class testClass) throws URISyntaxException { + return Paths.get(testClass.getResource("/" + called).toURI()).toFile(); + } + + public static void copyResourceIntoFile(File toFile, String resourcePath) { + createEmptyFile(toFile); + writeResourceToFile(toFile, resourcePath); + } + + public static void copyTestResourceIntoFile(File toFile, InputStream testResource) { + createEmptyFile(toFile); + copyResourceToFile(toFile, testResource); + } + + private static void copyResourceToFile(File toFile, InputStream testResource) { + try (InputStream in = testResource; + OutputStream out = new FileOutputStream(toFile)) { + copy(in, out); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static void writeResourceToFile(File toFile, String resourcePath) { + try (InputStream in = PlanPlugin.class.getResourceAsStream(resourcePath); + OutputStream out = new FileOutputStream(toFile)) { + if (in == null) { + throw new FileNotFoundException("Resource with name '" + resourcePath + "' not found"); + } + copy(in, out); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static void copy(InputStream in, OutputStream out) throws IOException { + int read; + byte[] bytes = new byte[1024]; + + while ((read = in.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + } + + private static void createEmptyFile(File toFile) { + String path = toFile.getAbsolutePath(); + try { + toFile.getParentFile().mkdirs(); + if (!toFile.exists() && !toFile.createNewFile()) { + throw new FileNotFoundException("Could not create file: " + path); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/Plan/common/src/test/resources/config/4.5.2-bungeeconfig.yml b/Plan/common/src/test/resources/config/4.5.2-bungeeconfig.yml new file mode 100644 index 0000000000..2b1595155c --- /dev/null +++ b/Plan/common/src/test/resources/config/4.5.2-bungeeconfig.yml @@ -0,0 +1,129 @@ +# ----------------------------------------------------- +# Plan Bungee Configuration file +# More information about each setting: +# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Bungee-Configuration +# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Bukkit-Configuration +# ----------------------------------------------------- +Server: + IP: 0.0.0.0 +Network: + Name: Plan + +Plugin: + Debug: 'false' + Locale: default + Check-for-updates: true + Notify-About-DEV-Releases: false + KeepLogsForXDays: 7 + +# ----------------------------------------------------- +# More information about SSL Certificate Settings: +# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/SSL-Certificate-%28HTTPS%29-Set-Up +# ----------------------------------------------------- +WebServer: + Port: 8804 + InternalIP: 0.0.0.0 + Security: + SSL-Certificate: + KeyStorePath: 'SSLCertificate.keystore' + KeyPass: 'default' + StorePass: 'default' + Alias: 'alias' +# ----------------------------------------------------- +Database: + MySQL: + Host: localhost + Port: 3306 + User: root + Password: minecraft + Database: Plan + # Launch options to append after driver address, for example + LaunchOptions: "?rewriteBatchedStatements=true&useSSL=false" +# ----------------------------------------------------- +Commands: + AlternativeIP: + Enabled: false + Link: your.domain.here:%port% + Colors: + Main: '&2' + Secondary: '&7' + Highlight: '&f' + +Analysis: + AutoRefreshPeriod: 60 + Active: + # Minutes a player should play per week to be considered active + PlaytimeThreshold: 30 + # How many days player should join per week to be considered active + LoginThreshold: 2 + Export: + Enabled: false + DestinationFolder: 'Analysis Results' + +Data: + # How many minutes player has to stay still to be considered AFK + AFKThresholdMinutes: 3 + Commands: + LogUnknownCommands: false + CombineCommandAliases: true + Geolocations: true + Ping: + ServerEnableDelaySeconds: 300 + PlayerLoginDelaySeconds: 30 + KeepInactivePlayerDataForDays: 180 +# ----------------------------------------------------- +Customization: + UseServerTime: true + Display: + SessionsAsTable: false + LargestWorldPercInSessionTitle: false + # By Default WorldPie is ordered alphabetically, colors are still determined alphabetically. + OrderWorldPieByPercentage: false + MaxSessions: 50 + MaxPlayers: 2500 + MaxPlayersPlayersPage: 25000 + PlayerTableFooter: true + PlayerIPs: true + GapsInGraphData: false + Formatting: + DecimalPoints: '#.##' + Dates: + # RecentDays replaces date with Today, Yesterday, Wednesday etc. + RecentDays: true + # Non-regex pattern to replace + DatePattern: 'MMM d YYYY' + Full: 'MMM d YYYY, HH:mm:ss' + NoSeconds: 'MMM d YYYY, HH:mm' + JustClock: 'HH:mm:ss' + TimeAmount: + Year: '1 year, ' + Years: '%years% years, ' + Month: '1 month, ' + Months: '%months% months, ' + Day: '1d ' + Days: '%days%d ' + Hours: '%hours%h ' + Minutes: '%minutes%m ' + Seconds: '%seconds%s' + Zero: '0s' + +# ----------------------------------------------------- +# More information about Themes: +# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Themes +# ----------------------------------------------------- +Theme: + Base: Default + Font: + FontStyleSheet: https://fonts.googleapis.com/css?family=Quicksand:300,400 + FontFamily: "'Quicksand', sans-serif" +# ----------------------------------------------------- +Servers: + Example: + WebServerPort: 8034 + ServerName: Example + ThemeBase: Default +# ----------------------------------------------------- +Plugins: + BuyCraft: + # http://help.buycraft.net/article/36-where-to-find-the-secret-key + Secret: "-" \ No newline at end of file diff --git a/Plan/common/src/test/resources/config/4.5.2-config.yml b/Plan/common/src/test/resources/config/4.5.2-config.yml new file mode 100644 index 0000000000..03e9018b62 --- /dev/null +++ b/Plan/common/src/test/resources/config/4.5.2-config.yml @@ -0,0 +1,155 @@ +# ----------------------------------------------------- +# Plan Bukkit Configuration file +# More information about each setting: +# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Bukkit-Configuration +# ----------------------------------------------------- +Server: + ServerName: 'Plan' + +# ----------------------------------------------------- +# More information about Locale +# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Localization +# ----------------------------------------------------- +Plugin: + Debug: false + Locale: default + WriteNewLocaleFileOnEnable: false + Bungee-Override: + StandaloneMode: false + CopyBungeeConfig: true + Check-for-updates: true + Notify-About-DEV-Releases: false + KeepLogsForXDays: 7 + +# ----------------------------------------------------- +# More information about SSL Certificate Settings: +# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/SSL-Certificate-%28HTTPS%29-Set-Up +# ----------------------------------------------------- +WebServer: + Port: 8804 + # InternalIP usually does not need to be changed, only change it if you know what you're doing! + # 0.0.0.0 allocates Internal (local) IP automatically for the WebServer. + InternalIP: 0.0.0.0 + Security: + SSL-Certificate: + KeyStorePath: 'SSLCertificate.keystore' + KeyPass: 'default' + StorePass: 'default' + Alias: 'alias' + # For those that want to serve Html from their own WebServer instead. + # Set up Html Export (https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/External-WebServer-Use) + # ATTENTION: On BungeeCord systems it is not possible to disable the WebServer on the plugin due to connection requirements. + # If the WebServer is disabled with this setting BungeeCord systems will cease to function. + DisableWebServer: false + ExternalWebServerAddress: "https://www.example.address" +# ----------------------------------------------------- +Database: + Type: SQLite + MySQL: + Host: localhost + Port: 3306 + User: root + Password: minecraft + Database: Plan + # Launch options to append after driver address, for example + LaunchOptions: "?rewriteBatchedStatements=true&useSSL=false" +# ----------------------------------------------------- +Commands: + AlternativeIP: + Enabled: false + Link: your.domain.here:%port% + Colors: + Main: '&2' + Secondary: '&7' + Highlight: '&f' + +Analysis: + AutoRefreshPeriod: 60 + Active: + # Minutes a player should play per week to be considered active + PlaytimeThreshold: 30 + # How many days player should join per week to be considered active + LoginThreshold: 2 + LogProgress: true + Export: + Enabled: false + DestinationFolder: 'Analysis Results' +Data: + # How many minutes player has to stay still to be considered AFK + AFKThresholdMinutes: 3 + Commands: + LogUnknownCommands: false + CombineCommandAliases: true + Geolocations: true + Ping: + ServerEnableDelaySeconds: 300 + PlayerLoginDelaySeconds: 30 + KeepInactivePlayerDataForDays: 180 +# ----------------------------------------------------- +Customization: + UseServerTime: true + Display: + SessionsAsTable: false + LargestWorldPercInSessionTitle: false + # By Default WorldPie is ordered alphabetically, colors are still determined alphabetically. + OrderWorldPieByPercentage: false + MaxSessions: 50 + MaxPlayers: 2500 + MaxPlayersPlayersPage: 25000 + PlayerTableFooter: true + PlayerIPs: true + GapsInGraphData: false + Formatting: + DecimalPoints: '#.##' + # Dates settings use Java SimpleDateFormat. + # You can find the patterns & examples here: + # https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html + Dates: + # RecentDays replaces date with Today, Yesterday, Wednesday etc. + RecentDays: true + # Non-regex pattern to replace + DatePattern: 'MMM d YYYY' + Full: 'MMM d YYYY, HH:mm:ss' + NoSeconds: 'MMM d YYYY, HH:mm' + JustClock: 'HH:mm:ss' + TimeAmount: + Year: '1 year, ' + Years: '%years% years, ' + Month: '1 month, ' + Months: '%months% months, ' + Day: '1d ' + Days: '%days%d ' + Hours: '%hours%h ' + Minutes: '%minutes%m ' + Seconds: '%seconds%s' + Zero: '0s' + WorldAliases: + world: world + +# ----------------------------------------------------- +# More information about Themes: +# https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/Themes +# +# Since 4.1.0 colors are set in theme.yml +# ----------------------------------------------------- +Theme: + Base: Default + Graphs: + TPS: + High-Threshold: 18 + Medium-Threshold: 10 + # Free Disk space thresholds, in megabytes. + Disk: + High-Threshold: 500 + Medium-Threshold: 100 +# ----------------------------------------------------- +Plugins: + Factions: + HideFactions: + - ExampleFaction + Towny: + HideTowns: + - ExampleTown + BuyCraft: + # http://help.buycraft.net/article/36-where-to-find-the-secret-key + Secret: "-" diff --git a/Plan/pom.xml b/Plan/pom.xml index 0590a9fcce..61a4bbec9b 100644 --- a/Plan/pom.xml +++ b/Plan/pom.xml @@ -81,6 +81,17 @@ 5.3.2 test + + org.junit.jupiter + junit-jupiter-params + 5.3.2 + test + + + org.junit-pioneer + junit-pioneer + 0.3.0 + org.mockito mockito-core