diff --git a/buildNumber.properties b/buildNumber.properties index 262667a2..2d1d14b9 100644 --- a/buildNumber.properties +++ b/buildNumber.properties @@ -1,3 +1,3 @@ #maven.buildNumber.plugin properties file -#Mon Aug 19 09:32:22 EDT 2024 -buildNumber=260 +#Mon Aug 19 12:41:14 EDT 2024 +buildNumber=276 diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 56a400f4..380b9a06 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -612,6 +612,8 @@ Small oit shader work (08/19/2024) Disable cloud ring +Undo oit shader work to fix build pipeline +Testing rearchitecting # TODO diff --git a/pom.xml b/pom.xml index 6f114c08..df9902e5 100644 --- a/pom.xml +++ b/pom.xml @@ -290,6 +290,9 @@ natives-linux + + + fast @@ -377,6 +380,9 @@ natives-windows + + + fast @@ -406,6 +412,21 @@ + + + + + + + integration + + + fast,integration + + + + + @@ -417,6 +438,8 @@ + + org.apache.maven.plugins maven-shade-plugin @@ -439,6 +462,9 @@ + + + org.codehaus.mojo exec-maven-plugin @@ -488,6 +514,9 @@ --> + + + org.codehaus.mojo buildnumber-maven-plugin diff --git a/src/test/java/annotations/FastTest.java b/src/test/java/annotations/FastTest.java new file mode 100644 index 00000000..c66b9a82 --- /dev/null +++ b/src/test/java/annotations/FastTest.java @@ -0,0 +1,26 @@ +package annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.Timeout.ThreadMode; + +/** + * A fast test that does not depend on setup/shutdown -- A unit test + */ + +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Tag("fast") +@Test +@Timeout( value = 20, unit = TimeUnit.MILLISECONDS, threadMode = ThreadMode.SAME_THREAD ) +public @interface FastTest { + +} diff --git a/src/test/java/annotations/IntegrationSetup.java b/src/test/java/annotations/IntegrationSetup.java new file mode 100644 index 00000000..3998f62d --- /dev/null +++ b/src/test/java/annotations/IntegrationSetup.java @@ -0,0 +1,21 @@ +package annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; + + +/** + * Used to flag work that should be done before each integration test + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@BeforeEach +@Tag("integration") +public @interface IntegrationSetup { + +} diff --git a/src/test/java/annotations/IntegrationTeardown.java b/src/test/java/annotations/IntegrationTeardown.java new file mode 100644 index 00000000..5c4e50e2 --- /dev/null +++ b/src/test/java/annotations/IntegrationTeardown.java @@ -0,0 +1,20 @@ +package annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Tag; + +/** + * Flags for work to be done tearing down after running an integration test + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@AfterEach +@Tag("integration") +public @interface IntegrationTeardown { + +} diff --git a/src/test/java/annotations/IntegrationTest.java b/src/test/java/annotations/IntegrationTest.java new file mode 100644 index 00000000..8c125369 --- /dev/null +++ b/src/test/java/annotations/IntegrationTest.java @@ -0,0 +1,26 @@ +package annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.Timeout.ThreadMode; + +/** + * An integration test. Has defaults for timeout on the test + */ + +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Tag("integration") +@Test +@Timeout( value = 2, unit = TimeUnit.MINUTES, threadMode = ThreadMode.SAME_THREAD ) +public @interface IntegrationTest { + +} diff --git a/src/test/java/db/DBTest.java b/src/test/java/db/DBTest.java deleted file mode 100644 index 666cd098..00000000 --- a/src/test/java/db/DBTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package db; - -public class DBTest { - -} diff --git a/src/test/java/entity/InventoryStateTest.java b/src/test/java/electrosphere/entity/InventoryStateTest.java similarity index 58% rename from src/test/java/entity/InventoryStateTest.java rename to src/test/java/electrosphere/entity/InventoryStateTest.java index ff64c5f1..2020e168 100644 --- a/src/test/java/entity/InventoryStateTest.java +++ b/src/test/java/electrosphere/entity/InventoryStateTest.java @@ -1,4 +1,4 @@ -package entity; +package electrosphere.entity; public class InventoryStateTest { diff --git a/src/test/java/entity/LifeStateTest.java b/src/test/java/electrosphere/entity/LifeStateTest.java similarity index 55% rename from src/test/java/entity/LifeStateTest.java rename to src/test/java/electrosphere/entity/LifeStateTest.java index 170d56e7..730a3264 100644 --- a/src/test/java/entity/LifeStateTest.java +++ b/src/test/java/electrosphere/entity/LifeStateTest.java @@ -1,4 +1,4 @@ -package entity; +package electrosphere.entity; public class LifeStateTest { diff --git a/src/test/java/entity/SpawningCreaturesTest.java b/src/test/java/electrosphere/entity/SpawningCreaturesTest.java similarity index 95% rename from src/test/java/entity/SpawningCreaturesTest.java rename to src/test/java/electrosphere/entity/SpawningCreaturesTest.java index 408c9c3c..e5b5c649 100644 --- a/src/test/java/entity/SpawningCreaturesTest.java +++ b/src/test/java/electrosphere/entity/SpawningCreaturesTest.java @@ -1,4 +1,4 @@ -package entity; +package electrosphere.entity; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -13,6 +13,7 @@ public class SpawningCreaturesTest { @BeforeEach public void initEngine(){ + LoggerInterface.initLoggers(); LoggerInterface.loggerEngine.INFO("[Test] Spawn many creatures"); Globals.RUN_CLIENT = true; Globals.RUN_SERVER = true; diff --git a/src/test/java/electrosphere/renderer/ui/elements/WindowIntegrationTest.java b/src/test/java/electrosphere/renderer/ui/elements/WindowIntegrationTest.java deleted file mode 100644 index 41e0af92..00000000 --- a/src/test/java/electrosphere/renderer/ui/elements/WindowIntegrationTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package electrosphere.renderer.ui.elements; - -import java.awt.image.BufferedImage; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; - -import electrosphere.engine.Globals; -import electrosphere.engine.Main; -import electrosphere.menu.WindowUtils; -import electrosphere.menu.mainmenu.MenuGeneratorsUITesting; -import electrosphere.renderer.RenderingEngine; -import testutils.TestEngineUtils; - -/** - * Integration tests for the window class - */ -public class WindowIntegrationTest { - - @BeforeEach - @Tag("integration") - /** - * Initializes the engine - */ - public void initEngine(){ - TestEngineUtils.initGraphicalEngine(); - } - - @Test - @Tag("integration") - /** - * Tests creating a window - */ - public void testCreateWindow(){ - //create ui testing window - TestEngineUtils.simulateFrames(1); - WindowUtils.replaceMainMenuContents(MenuGeneratorsUITesting.createUITestMenu()); - TestEngineUtils.simulateFrames(1); - BufferedImage screenshot = RenderingEngine.defaultFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState()); - - } - - @AfterEach - @Tag("integration") - /** - * Shuts down the engine - */ - public void closeEngine(){ - Main.shutdown(); - } - - - -} diff --git a/src/test/java/electrosphere/renderer/ui/elements/WindowTest.java b/src/test/java/electrosphere/renderer/ui/elements/WindowTest.java new file mode 100644 index 00000000..400ac003 --- /dev/null +++ b/src/test/java/electrosphere/renderer/ui/elements/WindowTest.java @@ -0,0 +1,27 @@ +package electrosphere.renderer.ui.elements; + +import annotations.IntegrationTest; +import electrosphere.menu.WindowUtils; +import electrosphere.menu.mainmenu.MenuGeneratorsUITesting; +import template.RenderingTestTemplate; +import testutils.TestEngineUtils; + +/** + * Tests for the window class + */ +public class WindowTest extends RenderingTestTemplate { + + /** + * Tests creating a window + */ + @IntegrationTest + public void testCreateWindow(){ + //create ui testing window + TestEngineUtils.simulateFrames(1); + WindowUtils.replaceMainMenuContents(MenuGeneratorsUITesting.createUITestMenu()); + TestEngineUtils.simulateFrames(1); + // TestRenderingUtils.saveTestRender("./test/java/electrosphere/renderer/ui/elements/window.png"); + this.checkRender("Basic", "./test/java/electrosphere/renderer/ui/elements/window.png"); + } + +} diff --git a/src/test/java/electrosphere/renderer/ui/elements/WindowUnitTest.java b/src/test/java/electrosphere/renderer/ui/elements/WindowUnitTest.java deleted file mode 100644 index d7ae1809..00000000 --- a/src/test/java/electrosphere/renderer/ui/elements/WindowUnitTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package electrosphere.renderer.ui.elements; - -/** - * Unit testing the window class - */ -public class WindowUnitTest { - - - -} diff --git a/src/test/java/startup/StartupTest.java b/src/test/java/integration/StartupTest.java similarity index 82% rename from src/test/java/startup/StartupTest.java rename to src/test/java/integration/StartupTest.java index c9462e0d..2256360e 100644 --- a/src/test/java/startup/StartupTest.java +++ b/src/test/java/integration/StartupTest.java @@ -1,16 +1,15 @@ -package startup; - -import org.junit.jupiter.api.Test; +package integration; +import annotations.IntegrationSetup; +import annotations.IntegrationTest; import electrosphere.engine.Globals; -import electrosphere.engine.Main; import electrosphere.engine.profiler.Profiler; import electrosphere.logger.LoggerInterface; import electrosphere.net.NetUtils; public class StartupTest { - @Test + @IntegrationSetup public void testStartupHeadless(){ LoggerInterface.loggerEngine.INFO("[Test] Startup Headless"); Globals.RUN_CLIENT = false; @@ -22,7 +21,7 @@ public class StartupTest { // Main.mainLoop(1); } - @Test + @IntegrationTest public void testEmpty() { LoggerInterface.loggerEngine.INFO("[Test] Empty test"); } diff --git a/src/test/java/networking/NetworkingTest.java b/src/test/java/networking/NetworkingTest.java deleted file mode 100644 index e7e4a378..00000000 --- a/src/test/java/networking/NetworkingTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package networking; - -public class NetworkingTest { - -} diff --git a/src/test/java/physics/PhysicsTest.java b/src/test/java/physics/PhysicsTest.java deleted file mode 100644 index ebfe64cb..00000000 --- a/src/test/java/physics/PhysicsTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package physics; - -public class PhysicsTest { - -} diff --git a/src/test/java/script/ScriptTest.java b/src/test/java/script/ScriptTest.java deleted file mode 100644 index c8411719..00000000 --- a/src/test/java/script/ScriptTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package script; - -public class ScriptTest { - -} diff --git a/src/test/java/template/RenderingTestTemplate.java b/src/test/java/template/RenderingTestTemplate.java new file mode 100644 index 00000000..2af58d49 --- /dev/null +++ b/src/test/java/template/RenderingTestTemplate.java @@ -0,0 +1,52 @@ +package template; + +import java.io.File; + +import annotations.IntegrationSetup; +import annotations.IntegrationTeardown; +import electrosphere.engine.Main; +import testutils.TestEngineUtils; +import testutils.TestRenderingUtils; + +/** + * A test class that involves testing renders + */ +public abstract class RenderingTestTemplate { + + /** + * Initializes the engine + */ + @IntegrationSetup + public void initEngine(){ + TestEngineUtils.initGraphicalEngine(); + } + + /** + * Shuts down the engine + */ + @IntegrationTeardown + public void closeEngine(){ + Main.shutdown(); + } + + /** + * Checks the most recent render versus an existing image + * @param renderName The name associated with the render + * @param existingRenderPath The path to the existing image + */ + public void checkRender(String renderName, String existingRenderPath){ + //of the format "electrosphere.renderer.ui.elements.WindowTest" + String canonicalName = this.getClass().getCanonicalName(); + + //check the render + TestRenderingUtils.assertEqualsRender(existingRenderPath, () -> { + + //on failure, save the failed render + String failureSavePath = "./.testcache/" + canonicalName + "-" + renderName + ".png"; + File saveFile = new File(failureSavePath); + System.err.println("[[ATTACHMENT|" + saveFile.getAbsolutePath() + "]]"); + TestRenderingUtils.saveTestRender(failureSavePath); + }); + } + +} diff --git a/src/test/java/testutils/TestRenderingUtils.java b/src/test/java/testutils/TestRenderingUtils.java new file mode 100644 index 00000000..d986f8ed --- /dev/null +++ b/src/test/java/testutils/TestRenderingUtils.java @@ -0,0 +1,66 @@ +package testutils; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import static org.junit.jupiter.api.Assertions.*; + +import electrosphere.engine.Globals; +import electrosphere.renderer.RenderingEngine; + +/** + * Utilities for comparing renders + */ +public class TestRenderingUtils { + + /** + * Asserts that the most recent render matches the image stored at the provided filepath + * @param existingRenderPath The filepath of the existing render + */ + public static void assertEqualsRender(String existingRenderPath, Runnable onFailure){ + BufferedImage testData = null; + try { + testData = ImageIO.read(new File(existingRenderPath)); + } catch (IOException e){ + fail("Failed to read existing image path " + existingRenderPath); + } + BufferedImage screenshot = RenderingEngine.defaultFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState()); + //check basic data + if(testData.getWidth() != screenshot.getWidth()){ + onFailure.run(); + } + assertEquals(testData.getHeight(), screenshot.getHeight()); + if(testData.getWidth() != screenshot.getWidth()){ + onFailure.run(); + } + assertEquals(testData.getHeight(), screenshot.getHeight()); + + //pixel-by-pixel check + for(int x = 0; x < testData.getWidth(); x++){ + for(int y = 0; y < testData.getHeight(); y++){ + if(testData.getRGB(x, y) != screenshot.getRGB(x, y)){ + onFailure.run(); + } + assertEquals(testData.getRGB(x, y),screenshot.getRGB(x, y)); + } + } + } + + /** + * Used for saving a copy of the current render (ie for generating test data) + * @param existingRenderPath The filepath of the existing render + */ + public static void saveTestRender(String existingRenderPath){ + BufferedImage screenshot = RenderingEngine.defaultFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState()); + try { + ImageIO.write(screenshot, "png", new File(existingRenderPath)); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} diff --git a/test/java/electrosphere/renderer/ui/elements/window.png b/test/java/electrosphere/renderer/ui/elements/window.png new file mode 100644 index 00000000..dd6ee3d0 Binary files /dev/null and b/test/java/electrosphere/renderer/ui/elements/window.png differ