diff --git a/src/functionalTest/java/codechicken/multipart/test/MultipartModFunctionalTest.java b/src/functionalTest/java/codechicken/multipart/test/MultipartModFunctionalTest.java new file mode 100644 index 0000000..e42a3bf --- /dev/null +++ b/src/functionalTest/java/codechicken/multipart/test/MultipartModFunctionalTest.java @@ -0,0 +1,57 @@ +package codechicken.multipart.test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; + +import org.junit.jupiter.api.Test; + +import codechicken.multipart.ControlKeyModifer; +import codechicken.multipart.MultiPartRegistry; +import codechicken.multipart.handler.MultipartMod; +import codechicken.multipart.handler.MultipartMod$; +import codechicken.multipart.handler.MultipartProxy; +import codechicken.multipart.handler.MultipartSaveLoad; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.ModContainer; + +class MultipartModFunctionalTest { + + @Test + void fmlUsesTheCompanionAndCompletesTheMultipartLifecycle() { + ModContainer container = Loader.instance().getIndexedModList().get("ForgeMultipart"); + assertNotNull(container); + assertSame(MultipartMod$.MODULE$, container.getMod()); + assertTrue(MultiPartRegistry.loaded()); + assertNotNull(MultipartProxy.block()); + assertNotNull(MultipartProxy.logger()); + } + + @Test + void serverStoppedClearsTransientWorldAndControlState() { + World originalWorld = MultipartSaveLoad.loadingWorld(); + Map controls = ControlKeyModifer.map(); + Map originalControls = new HashMap<>(controls); + try { + MultipartSaveLoad.loadingWorld_$eq(MinecraftServer.getServer().worldServers[0]); + controls.put(null, Boolean.TRUE); + + MultipartMod.serverStopped(null); + + assertNull(MultipartSaveLoad.loadingWorld()); + assertTrue(controls.isEmpty()); + } finally { + MultipartSaveLoad.loadingWorld_$eq(originalWorld); + controls.clear(); + controls.putAll(originalControls); + } + } +} diff --git a/src/test/java/codechicken/multipart/handler/MultipartModCharacterizationTest.java b/src/test/java/codechicken/multipart/handler/MultipartModCharacterizationTest.java new file mode 100644 index 0000000..b0f9fdd --- /dev/null +++ b/src/test/java/codechicken/multipart/handler/MultipartModCharacterizationTest.java @@ -0,0 +1,79 @@ +package codechicken.multipart.handler; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Set; +import java.util.TreeSet; + +import org.junit.jupiter.api.Test; +import org.objectweb.asm.Type; + +import codechicken.multipart.Tags; +import cpw.mods.fml.common.Mod; + +class MultipartModCharacterizationTest { + + private static final Set EVENT_METHODS = new TreeSet<>( + Arrays.asList( + "beforeServerStart(Lcpw/mods/fml/common/event/FMLServerAboutToStartEvent;)V", + "init(Lcpw/mods/fml/common/event/FMLInitializationEvent;)V", + "postInit(Lcpw/mods/fml/common/event/FMLPostInitializationEvent;)V", + "preInit(Lcpw/mods/fml/common/event/FMLPreInitializationEvent;)V", + "serverStopped(Lcpw/mods/fml/common/event/FMLServerStoppedEvent;)V")); + + @Test + void keepsBothAnnotatedSingletonTypesAndLifecycleMethods() throws Exception { + assertModType(MultipartMod.class, true); + assertModType(MultipartMod$.class, false); + + assertEquals(0, MultipartMod.class.getFields().length); + Field module = MultipartMod$.class.getField("MODULE$"); + assertSame(MultipartMod$.class, module.getType()); + assertTrue(Modifier.isStatic(module.getModifiers())); + assertTrue(Modifier.isFinal(module.getModifiers())); + assertSame(MultipartMod$.MODULE$, module.get(null)); + } + + @Test + void packetHandlerChannelUsesTheModCompanionIdentity() throws Exception { + assertSame(MultipartMod$.MODULE$, new MultipartPH().channel()); + assertSame(MultipartMod$.class, MultipartPH.class.getDeclaredMethod("channel").getReturnType()); + assertSame(MultipartMod$.class, MultipartPH.class.getDeclaredField("channel").getType()); + } + + private static void assertModType(Class type, boolean staticMethods) { + assertTrue(Modifier.isPublic(type.getModifiers())); + assertTrue(Modifier.isFinal(type.getModifiers())); + assertEquals(EVENT_METHODS, publicMethodSignatures(type)); + + Mod mod = type.getAnnotation(Mod.class); + assertEquals("ForgeMultipart", mod.modid()); + assertEquals("Forge Multipart", mod.name()); + assertEquals("[1.7.10]", mod.acceptedMinecraftVersions()); + assertEquals(Tags.VERSION, mod.version()); + assertEquals("scala", mod.modLanguage()); + + for (Method method : type.getDeclaredMethods()) { + if (Modifier.isPublic(method.getModifiers())) { + assertTrue(method.isAnnotationPresent(Mod.EventHandler.class)); + assertEquals(staticMethods, Modifier.isStatic(method.getModifiers())); + } + } + } + + private static Set publicMethodSignatures(Class type) { + Set signatures = new TreeSet<>(); + for (Method method : type.getDeclaredMethods()) { + if (Modifier.isPublic(method.getModifiers())) { + signatures.add(method.getName() + Type.getMethodDescriptor(method)); + } + } + return signatures; + } +}