From 2ec35ed0ccaf797a613d963f9cdc490cd05f403d Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sat, 30 May 2026 22:58:37 -0700 Subject: [PATCH] Fix test environment writing config files to project root BukkitConfig calls mcMMO.p.getDataFolder() in its constructor to determine where to write config files. When tests mock mcMMO.p but don't stub getDataFolder(), it returns null, which Java resolves to the current working directory (the project root), causing files like experience.yml to be created there. Fix by stubbing mcMMO.p.getDataFolder() with a fresh temporary directory in every test setup that mocks mcMMO.p: - MMOTestEnvironment.mockBaseEnvironment(): creates testDataFolder in temp and deletes it in cleanUpStaticMocks() - SQLDatabaseManagerTest.setUpAll(): same pattern, cleaned in tearDownAll() - FlatFileDatabaseManagerTest.initBeforeAll(): same pattern, cleaned in the new tearDownAll() method Also remove the .gitignore band-aid entries that were added to paper over the symptom. --- .gitignore | 11 -------- .../com/gmail/nossr50/MMOTestEnvironment.java | 25 +++++++++++++++++++ .../database/FlatFileDatabaseManagerTest.java | 16 ++++++++++++ .../database/SQLDatabaseManagerTest.java | 24 ++++++++++++++++++ 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index baa30b466..e3369e339 100644 --- a/.gitignore +++ b/.gitignore @@ -50,17 +50,6 @@ # Project Stuff /src/main/resources/mcMMO -# Config files that tests can accidentally write to the project root -# when mcMMO.p.getDataFolder() returns null (resolves to cwd) -/experience.yml -/config.yml -/advanced.yml -/fishing_treasures.yml -/treasures.yml -/sounds.yml -/potions.yml -/skillranks.yml - # Other Libraries *.jar diff --git a/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java b/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java index b84d4c44b..63d02053a 100644 --- a/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java +++ b/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java @@ -30,6 +30,8 @@ import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.SkillTools; import com.gmail.nossr50.util.sounds.SoundManager; +import java.io.File; +import java.io.IOException; import java.util.UUID; import java.util.logging.Logger; import org.bukkit.Bukkit; @@ -85,11 +87,18 @@ public abstract class MMOTestEnvironment { protected MaterialMapStore materialMapStore; protected MinecraftGameVersion minecraftGameVersion; + protected File testDataFolder; protected void mockBaseEnvironment(Logger logger) throws InvalidSkillException { mockedMcMMO = mockStatic(mcMMO.class); mcMMO.p = mock(mcMMO.class); when(mcMMO.p.getLogger()).thenReturn(logger); + try { + testDataFolder = java.nio.file.Files.createTempDirectory("mcmmo-test-data-").toFile(); + } catch (IOException e) { + throw new RuntimeException("Failed to create temp test data folder", e); + } + when(mcMMO.p.getDataFolder()).thenReturn(testDataFolder); // Game version minecraftGameVersion = mock(MinecraftGameVersion.class); @@ -279,5 +288,21 @@ public abstract class MMOTestEnvironment { if (mockedSoundManager != null) { mockedSoundManager.close(); } + if (testDataFolder != null) { + deleteRecursively(testDataFolder); + testDataFolder = null; + } + } + + private static void deleteRecursively(final File file) { + if (file.isDirectory()) { + final File[] children = file.listFiles(); + if (children != null) { + for (final File child : children) { + deleteRecursively(child); + } + } + } + file.delete(); } } diff --git a/src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java b/src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java index 463931b8c..9f7c43473 100644 --- a/src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java +++ b/src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java @@ -45,6 +45,7 @@ import java.util.logging.Logger; import org.bukkit.Server; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -55,6 +56,8 @@ import org.mockito.Mockito; @Tag("docker") class FlatFileDatabaseManagerTest { + private static File testDataFolder; + public static final @NotNull String TEST_FILE_NAME = "test.mcmmo.users"; public static final @NotNull String BAD_FILE_LINE_ONE = "mrfloris:2420:::0:2452:0:1983:1937:1790:3042:1138:3102:2408:3411:0:0:0:0:0:0:0:0::642:0:1617583171:0:1617165043:0:1617583004:1617563189:1616785408::2184:0:0:1617852413:HEARTS:415:0:631e3896-da2a-4077-974b-d047859d76bc:5:1600906906:"; public static final @NotNull String BAD_DATA_FILE_LINE_TWENTY_THREE = "nossr51:baddata:::baddata:baddata:640:baddata:1000:1000:1000:baddata:baddata:baddata:baddata:16:0:500:20273:0:0:0:0::1000:0:0:baddata:1593543012:0:0:0:0::1000:0:0:baddata:IGNORED:1000:0:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1:0:"; @@ -100,6 +103,12 @@ class FlatFileDatabaseManagerTest { // GIVEN a fully mocked mcMMO environment mcMMO.p = Mockito.mock(mcMMO.class); when(mcMMO.p.getLogger()).thenReturn(logger); + try { + testDataFolder = java.nio.file.Files.createTempDirectory("mcmmo-flatfile-test-data-").toFile(); + } catch (java.io.IOException e) { + throw new RuntimeException("Failed to create temp test data folder", e); + } + when(mcMMO.p.getDataFolder()).thenReturn(testDataFolder); // Null player lookup, shouldn't affect tests Server server = mock(Server.class); @@ -118,6 +127,13 @@ class FlatFileDatabaseManagerTest { return tempDir.getPath() + File.separator + TEST_FILE_NAME; } + @AfterAll + static void tearDownAll() { + if (testDataFolder != null) { + recursiveDelete(testDataFolder); + } + } + @AfterEach void tearDown() { recursiveDelete(tempDir); diff --git a/src/test/java/com/gmail/nossr50/database/SQLDatabaseManagerTest.java b/src/test/java/com/gmail/nossr50/database/SQLDatabaseManagerTest.java index 39e993554..44f9eba47 100644 --- a/src/test/java/com/gmail/nossr50/database/SQLDatabaseManagerTest.java +++ b/src/test/java/com/gmail/nossr50/database/SQLDatabaseManagerTest.java @@ -25,6 +25,8 @@ import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.platform.MinecraftGameVersion; import com.gmail.nossr50.util.skills.SkillTools; import com.gmail.nossr50.util.upgrade.UpgradeManager; +import java.io.File; +import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -82,6 +84,7 @@ class SQLDatabaseManagerTest { private static UpgradeManager upgradeManager; private static SkillTools skillTools; private static MinecraftGameVersion minecraftGameVersion; + private static File testDataFolder; // --- DB flavors you support --- enum DbFlavor { @@ -102,6 +105,12 @@ class SQLDatabaseManagerTest { mockedMcMMO = Mockito.mockStatic(mcMMO.class); mcMMO.p = Mockito.mock(mcMMO.class); when(mcMMO.p.getLogger()).thenReturn(logger); + try { + testDataFolder = java.nio.file.Files.createTempDirectory("mcmmo-sql-test-data-").toFile(); + } catch (IOException e) { + throw new RuntimeException("Failed to create temp test data folder", e); + } + when(mcMMO.p.getDataFolder()).thenReturn(testDataFolder); when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion); mockGeneralConfigBase(); @@ -127,6 +136,21 @@ class SQLDatabaseManagerTest { @AfterAll static void tearDownAll() { mockedMcMMO.close(); + if (testDataFolder != null) { + deleteRecursively(testDataFolder); + } + } + + private static void deleteRecursively(final File file) { + if (file.isDirectory()) { + final File[] children = file.listFiles(); + if (children != null) { + for (final File child : children) { + deleteRecursively(child); + } + } + } + file.delete(); } private static void mockGeneralConfigBase() {