From b7d067123cf90dad75adf8729081d5ae66fb08da Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 14 Nov 2024 19:50:08 +0800 Subject: [PATCH] Implement more detailed world manager tests --- build.gradle | 2 +- .../multiverse/core/TestWithMockBukkit.kt | 10 +- .../multiverse/core/mock/MVServerMock.java | 53 ++++++ .../multiverse/core/mock/MVWorldMock.java | 30 +++ .../multiverse/core/world/WorldManagerTest.kt | 178 +++++++++++++++++- 5 files changed, 261 insertions(+), 12 deletions(-) create mode 100644 src/test/java/org/mvplugins/multiverse/core/mock/MVServerMock.java create mode 100644 src/test/java/org/mvplugins/multiverse/core/mock/MVWorldMock.java diff --git a/build.gradle b/build.gradle index c71b9a63..05403606 100644 --- a/build.gradle +++ b/build.gradle @@ -136,7 +136,7 @@ dependencies { // Tests testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21' - testImplementation 'com.github.seeseemelk:MockBukkit-v1.21:3.133.0' + testImplementation 'com.github.seeseemelk:MockBukkit-v1.21:3.133.2' testImplementation('com.googlecode.json-simple:json-simple:1.1.1') { exclude group: 'junit', module: 'junit' } diff --git a/src/test/java/org/mvplugins/multiverse/core/TestWithMockBukkit.kt b/src/test/java/org/mvplugins/multiverse/core/TestWithMockBukkit.kt index 6521180c..f77f4d52 100644 --- a/src/test/java/org/mvplugins/multiverse/core/TestWithMockBukkit.kt +++ b/src/test/java/org/mvplugins/multiverse/core/TestWithMockBukkit.kt @@ -1,27 +1,31 @@ package org.mvplugins.multiverse.core import be.seeseemelk.mockbukkit.MockBukkit -import be.seeseemelk.mockbukkit.ServerMock +import com.dumptruckman.minecraft.util.Logging import org.mvplugins.multiverse.core.inject.PluginServiceLocator +import org.mvplugins.multiverse.core.mock.MVServerMock import org.mvplugins.multiverse.core.utils.TestingMode import kotlin.test.AfterTest import kotlin.test.BeforeTest +import kotlin.test.assertNotNull /** * Basic abstract test class that sets up MockBukkit and MultiverseCore. */ abstract class TestWithMockBukkit { - protected lateinit var server: ServerMock + protected lateinit var server: MVServerMock protected lateinit var multiverseCore: MultiverseCore protected lateinit var serviceLocator : PluginServiceLocator @BeforeTest fun setUpMockBukkit() { TestingMode.enable() - server = MockBukkit.mock() + server = MockBukkit.mock(MVServerMock()) multiverseCore = MockBukkit.load(MultiverseCore::class.java) + Logging.setDebugLevel(3) serviceLocator = multiverseCore.serviceLocator + assertNotNull(server.commandMap) } @AfterTest diff --git a/src/test/java/org/mvplugins/multiverse/core/mock/MVServerMock.java b/src/test/java/org/mvplugins/multiverse/core/mock/MVServerMock.java new file mode 100644 index 00000000..ff802cc5 --- /dev/null +++ b/src/test/java/org/mvplugins/multiverse/core/mock/MVServerMock.java @@ -0,0 +1,53 @@ +package org.mvplugins.multiverse.core.mock; + +import be.seeseemelk.mockbukkit.ServerMock; +import be.seeseemelk.mockbukkit.WorldMock; +import be.seeseemelk.mockbukkit.command.MockCommandMap; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class MVServerMock extends ServerMock { + + private final File worldContainer; + + public MVServerMock() throws IOException { + super(); + this.worldContainer = Files.createTempDirectory("world-container").toFile(); + this.worldContainer.deleteOnExit(); + System.out.println("Created test world folder: " + this.worldContainer.getAbsolutePath()); + } + + // This is required for acf reflection to work + @Override + public @NotNull MockCommandMap getCommandMap() { + return super.getCommandMap(); + } + + @Override + public @NotNull File getWorldContainer() { + return this.worldContainer; + } + + @Override + public World createWorld(@NotNull WorldCreator creator) { + WorldMock world = new MVWorldMock(creator); + world.getWorldFolder().mkdirs(); + createFile(new File(world.getWorldFolder(), "uid.dat")); + createFile(new File(world.getWorldFolder(), "level.dat")); + addWorld(world); + return world; + } + + private void createFile(File file) { + try { + file.createNewFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/org/mvplugins/multiverse/core/mock/MVWorldMock.java b/src/test/java/org/mvplugins/multiverse/core/mock/MVWorldMock.java new file mode 100644 index 00000000..ecff0590 --- /dev/null +++ b/src/test/java/org/mvplugins/multiverse/core/mock/MVWorldMock.java @@ -0,0 +1,30 @@ +package org.mvplugins.multiverse.core.mock; + +import be.seeseemelk.mockbukkit.MockBukkit; +import be.seeseemelk.mockbukkit.WorldMock; +import org.bukkit.WorldCreator; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class MVWorldMock extends WorldMock { + + private final File worldFolder; + private final boolean generateStructures; + + public MVWorldMock(@NotNull WorldCreator creator) { + super(creator); + this.worldFolder = new File(MockBukkit.getMock().getWorldContainer(), getName()); + this.generateStructures = creator.generateStructures(); + } + + @Override + public @NotNull File getWorldFolder() { + return this.worldFolder; + } + + @Override + public boolean canGenerateStructures() { + return this.generateStructures; + } +} diff --git a/src/test/java/org/mvplugins/multiverse/core/world/WorldManagerTest.kt b/src/test/java/org/mvplugins/multiverse/core/world/WorldManagerTest.kt index b735f383..858c543f 100644 --- a/src/test/java/org/mvplugins/multiverse/core/world/WorldManagerTest.kt +++ b/src/test/java/org/mvplugins/multiverse/core/world/WorldManagerTest.kt @@ -1,47 +1,209 @@ package org.mvplugins.multiverse.core.world +import org.bukkit.Bukkit import org.bukkit.World import org.bukkit.WorldType import org.mvplugins.multiverse.core.TestWithMockBukkit +import org.mvplugins.multiverse.core.world.options.CloneWorldOptions import org.mvplugins.multiverse.core.world.options.CreateWorldOptions +import org.mvplugins.multiverse.core.world.options.RegenWorldOptions +import org.mvplugins.multiverse.core.world.options.UnloadWorldOptions +import org.mvplugins.multiverse.core.world.reasons.CloneFailureReason +import org.mvplugins.multiverse.core.world.reasons.CreateFailureReason +import org.mvplugins.multiverse.core.world.reasons.LoadFailureReason +import java.io.File import kotlin.test.* class WorldManagerTest : TestWithMockBukkit() { private lateinit var worldManager: WorldManager private lateinit var world: LoadedMultiverseWorld + private lateinit var world2: LoadedMultiverseWorld @BeforeTest fun setUp() { worldManager = serviceLocator.getActiveService(WorldManager::class.java).takeIf { it != null } ?: run { throw IllegalStateException("WorldManager is not available as a service") } - worldManager.createWorld(CreateWorldOptions.worldName("world")) + assertTrue(worldManager.createWorld(CreateWorldOptions.worldName("world")).isSuccess) world = worldManager.getLoadedWorld("world").get() assertNotNull(world) + + assertTrue(worldManager.createWorld(CreateWorldOptions.worldName("world2")).isSuccess) + world2 = worldManager.getLoadedWorld("world2").get() + assertNotNull(world2) } @Test - fun `Creates a new world`() { - worldManager.createWorld(CreateWorldOptions.worldName("world_nether") + fun `Create world with custom options`() { + assertTrue(worldManager.createWorld(CreateWorldOptions.worldName("world_nether") .environment(World.Environment.NETHER) .generateStructures(false) .seed(1234L) - .useSpawnAdjust(true) + .useSpawnAdjust(false) .worldType(WorldType.FLAT) - ) + ).isSuccess) - val world = worldManager.getLoadedWorld("world_nether").get() + val getWorld = worldManager.getLoadedWorld("world_nether") + assertTrue(getWorld.isDefined) + val world = getWorld.get() assertNotNull(world) assertEquals("world_nether", world.name) assertEquals(World.Environment.NETHER, world.environment) - assertEquals("", world.generator) + assertFalse(world.canGenerateStructures().get()) assertEquals(1234L, world.seed) + assertFalse(world.adjustSpawn) + assertEquals(WorldType.FLAT, world.worldType.get()) + assertEquals("", world.generator) + } + + @Test + fun `Create world failed - invalid worldname`() { + assertEquals( + CreateFailureReason.INVALID_WORLDNAME, + worldManager.createWorld(CreateWorldOptions.worldName("*!@^&#*(")).failureReason + ) + } + + @Test + fun `Create world failed - world exists and loaded`() { + assertEquals( + CreateFailureReason.WORLD_EXIST_LOADED, + worldManager.createWorld(CreateWorldOptions.worldName("world")).failureReason + ) + } + + @Test + fun `Create world failed - world exists but unloaded`() { + assertTrue(worldManager.unloadWorld(UnloadWorldOptions.world(world)).isSuccess) + assertEquals( + CreateFailureReason.WORLD_EXIST_UNLOADED, + worldManager.createWorld(CreateWorldOptions.worldName("world")).failureReason + ) + } + + @Test + fun `Create world failed - world folder exists`() { + File(Bukkit.getWorldContainer(), "worldfolder").mkdir() + assertEquals( + CreateFailureReason.WORLD_EXIST_FOLDER, + worldManager.createWorld(CreateWorldOptions.worldName("worldfolder")).failureReason + ) + } + + @Test + fun `Remove world`() { + assertTrue(worldManager.removeWorld(world).isSuccess) + assertFalse(worldManager.getWorld("world").isDefined) + assertFalse(worldManager.getLoadedWorld("world").isDefined) + assertFalse(worldManager.getUnloadedWorld("world").isDefined) } @Test fun `Delete world`() { - worldManager.deleteWorld(world) + assertTrue(worldManager.deleteWorld(world).isSuccess) assertFalse(worldManager.getLoadedWorld("world").isDefined) } + + @Test + fun `Unload and load world`() { + assertTrue(worldManager.unloadWorld(UnloadWorldOptions.world(world2).saveBukkitWorld(true)).isSuccess) + assertFalse(world2.isLoaded) + assertFalse(world2.bukkitWorld.isDefined) + assertFalse(worldManager.getLoadedWorld("world2").isDefined) + assertTrue(worldManager.getWorld("world2").isDefined) + assertTrue(worldManager.getUnloadedWorld("world2").isDefined) + + assertTrue(worldManager.loadWorld("world2").isSuccess) + assertTrue(world2.isLoaded) + // todo: think what to do when a world is re-loaded with a different uid + // assertTrue(world2.bukkitWorld.isDefined) + assertTrue(worldManager.getLoadedWorld("world2").isDefined) + assertFalse(worldManager.getUnloadedWorld("world2").isDefined) + } + + @Test + fun `Load world failed - non-existent world`() { + assertEquals( + LoadFailureReason.WORLD_NON_EXISTENT, + worldManager.loadWorld("ghost").failureReason + ) + } + + @Test + fun `Load world failed - world folder exists but not imported`() { + File(Bukkit.getWorldContainer(), "worldfolder").mkdir() + File(Bukkit.getWorldContainer(), "worldfolder/level.dat").createNewFile() + assertEquals( + LoadFailureReason.WORLD_EXIST_FOLDER, + worldManager.loadWorld("worldfolder").failureReason + ) + } + + @Test + fun `Regen world`() { + assertTrue(worldManager.regenWorld(RegenWorldOptions + .world(world2) + .seed(4321L) + ).isSuccess) + + val getWorld = worldManager.getLoadedWorld("world2") + assertTrue(getWorld.isDefined) + val world = getWorld.get() + assertNotNull(world) + assertEquals(4321L, world.seed) + } + + @Test + fun `Clone world`() { + assertTrue(worldManager.cloneWorld(CloneWorldOptions.fromTo(world, "cloneworld")).isSuccess) + val getWorld = worldManager.getLoadedWorld("cloneworld") + assertTrue(getWorld.isDefined) + val world = getWorld.get() + assertNotNull(world) + assertEquals("cloneworld", world.name) + } + + @Test + fun `Clone world failed - invalid world name`() { + assertEquals( + CloneFailureReason.INVALID_WORLDNAME, + worldManager.cloneWorld(CloneWorldOptions.fromTo(world, "HU(@*!#")).failureReason + ) + } + + @Test + fun `Clone world failed - target world exists and loaded`() { + assertEquals( + CloneFailureReason.WORLD_EXIST_LOADED, + worldManager.cloneWorld(CloneWorldOptions.fromTo(world, "world2")).failureReason + ) + } + + @Test + fun `Clone world failed - target world exists but unloaded`() { + assertTrue(worldManager.unloadWorld(UnloadWorldOptions.world(world2)).isSuccess) + assertEquals( + CloneFailureReason.WORLD_EXIST_UNLOADED, + worldManager.cloneWorld(CloneWorldOptions.fromTo(world, "world2")).failureReason + ) + } + + @Test + fun `Clone world failed - target world folder exists`() { + File(Bukkit.getWorldContainer(), "worldfolder").mkdir() + assertEquals( + CloneFailureReason.WORLD_EXIST_FOLDER, + worldManager.cloneWorld(CloneWorldOptions.fromTo(world, "worldfolder")).failureReason + ) + } + + @Test + fun `Get potential worlds`() { + File(Bukkit.getWorldContainer(), "newworld1").mkdir() + File(Bukkit.getWorldContainer(), "newworld1/level.dat").createNewFile() + File(Bukkit.getWorldContainer(), "newworld2").mkdir() + File(Bukkit.getWorldContainer(), "newworld2/level.dat").createNewFile() + assertEquals(listOf("newworld1", "newworld2"), worldManager.getPotentialWorlds()) + } }