From bb3109d0f156b6fce25c569506c87035a80ac299 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sat, 6 Jan 2024 20:27:24 +0000 Subject: [PATCH 01/28] Add JUnit 5 dependency --- build.gradle | 7 +++++++ gradle.properties | 2 ++ 2 files changed, 9 insertions(+) diff --git a/build.gradle b/build.gradle index bff0f452..477df10d 100644 --- a/build.gradle +++ b/build.gradle @@ -47,6 +47,13 @@ subprojects { officialMojangMappings() parchment("org.parchmentmc.data:parchment-${parchmentAppendix}:${parchmentVersion}@zip") } + + testImplementation(platform("org.junit:junit-bom:${rootProject.junit_version}")) + testImplementation("org.junit.jupiter:junit-jupiter") + } + + test { + useJUnitPlatform() } } diff --git a/gradle.properties b/gradle.properties index 40d76a0f..9dcae165 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,3 +38,5 @@ neoforge_req=[20,) # https://mvnrepository.com/artifact/me.shedaniel.cloth/cloth-config?repo=architectury modmenu_version=9.0.0-pre.1 cloth_version=13.0.114 + +junit_version=5.10.1 \ No newline at end of file From 5358c5e94027a5920f6d20942fa418b26ee000bf Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sat, 6 Jan 2024 20:53:29 +0000 Subject: [PATCH 02/28] Add Mockito dependency --- build.gradle | 2 ++ gradle.properties | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 477df10d..7acb35ea 100644 --- a/build.gradle +++ b/build.gradle @@ -50,6 +50,8 @@ subprojects { testImplementation(platform("org.junit:junit-bom:${rootProject.junit_version}")) testImplementation("org.junit.jupiter:junit-jupiter") + testImplementation "org.mockito:mockito-core:${rootProject.mockito_version}" + testImplementation "org.mockito:mockito-junit-jupiter:${rootProject.mockito_version}" } test { diff --git a/gradle.properties b/gradle.properties index 9dcae165..8134f30c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,4 +39,5 @@ neoforge_req=[20,) modmenu_version=9.0.0-pre.1 cloth_version=13.0.114 -junit_version=5.10.1 \ No newline at end of file +junit_version=5.10.1 +mockito_version=5.8.0 \ No newline at end of file From 6b3ffabfdc2da51e5736a3dd5f9365b4d3637ee6 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sat, 6 Jan 2024 21:47:55 +0000 Subject: [PATCH 03/28] Use `run` working directory for tests --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 7acb35ea..7d7cfc05 100644 --- a/build.gradle +++ b/build.gradle @@ -55,6 +55,9 @@ subprojects { } test { + def dir = project.file "run" + dir.mkdirs() + workingDir dir useJUnitPlatform() } } From 41305053486d6566cd459bbe90f4b7364464f166 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Sat, 6 Jan 2024 21:32:06 +0000 Subject: [PATCH 04/28] Create BootstrapMinecraft annotation Since 1.17, Minecraft checks whether `Bootstrap` has been called, when any of its registries static constructor runs. This means we have to explicitly bootstrap test cases that use any of the registries. Added an annotation `@BootstrapMinecraft` to support this. --- .../test/extension/BootstrapMinecraft.java | 16 ++++++++++++++++ .../extension/BootstrapMinecraftExtension.java | 15 +++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraft.java create mode 100644 common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraftExtension.java diff --git a/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraft.java b/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraft.java new file mode 100644 index 00000000..9d13b5ed --- /dev/null +++ b/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraft.java @@ -0,0 +1,16 @@ +package net.xolt.freecam.test.extension; + +import org.junit.jupiter.api.extension.ExtendWith; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Ensure Minecraft is bootstrapped before running tests. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@ExtendWith(BootstrapMinecraftExtension.class) +public @interface BootstrapMinecraft {} diff --git a/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraftExtension.java b/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraftExtension.java new file mode 100644 index 00000000..b6a36253 --- /dev/null +++ b/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraftExtension.java @@ -0,0 +1,15 @@ +package net.xolt.freecam.test.extension; + +import net.minecraft.SharedConstants; +import net.minecraft.server.Bootstrap; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.Extension; +import org.junit.jupiter.api.extension.ExtensionContext; + +public class BootstrapMinecraftExtension implements Extension, BeforeAllCallback { + @Override + public void beforeAll(ExtensionContext context) { + SharedConstants.tryDetectVersion(); + Bootstrap.bootStrap(); + } +} From 960e2952732f399342e906a2b8fd79f05bb35b98 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sat, 6 Jan 2024 20:27:40 +0000 Subject: [PATCH 05/28] Stub FreecamPosition test --- .../freecam/util/FreecamPositionTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java new file mode 100644 index 00000000..5cb005fe --- /dev/null +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -0,0 +1,38 @@ +package net.xolt.freecam.util; + +import net.xolt.freecam.test.extension.BootstrapMinecraft; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +@BootstrapMinecraft +class FreecamPositionTest { + + @BeforeEach + void setUp() { + } + + @AfterEach + void tearDown() { + } + + @Test + void setRotation() { + } + + @Test + void mirrorRotation() { + } + + @Test + void moveForward() { + } + + @Test + void move() { + } + + @Test + void getChunkPos() { + } +} \ No newline at end of file From dd36db94f7febaaff3bc9ea8caa6a59df726be2c Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sat, 6 Jan 2024 21:48:22 +0000 Subject: [PATCH 06/28] Continue stubbing initial test --- .../net/xolt/freecam/util/FreecamPositionTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index 5cb005fe..17cee179 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -1,15 +1,25 @@ package net.xolt.freecam.util; +import net.minecraft.client.player.RemotePlayer; import net.xolt.freecam.test.extension.BootstrapMinecraft; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; @BootstrapMinecraft +@ExtendWith(MockitoExtension.class) class FreecamPositionTest { + @Mock RemotePlayer player; + private FreecamPosition position; + @BeforeEach void setUp() { + position = new FreecamPosition(player); } @AfterEach @@ -18,6 +28,10 @@ void tearDown() { @Test void setRotation() { + position.setRotation(10, 20); + Assertions.assertAll( + () -> Assertions.assertEquals(10, position.yaw), + () -> Assertions.assertEquals(20, position.pitch)); } @Test From badced0451970b319b6b497d6180d4a98d05ab18 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 12 Jan 2024 15:46:52 +0000 Subject: [PATCH 07/28] Add AssertJ dependency --- build.gradle | 1 + gradle.properties | 1 + 2 files changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 7d7cfc05..ac0ad5c5 100644 --- a/build.gradle +++ b/build.gradle @@ -50,6 +50,7 @@ subprojects { testImplementation(platform("org.junit:junit-bom:${rootProject.junit_version}")) testImplementation("org.junit.jupiter:junit-jupiter") + testImplementation "org.assertj:assertj-core:${rootProject.assertj_version}" testImplementation "org.mockito:mockito-core:${rootProject.mockito_version}" testImplementation "org.mockito:mockito-junit-jupiter:${rootProject.mockito_version}" } diff --git a/gradle.properties b/gradle.properties index 8134f30c..973558b1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,4 +40,5 @@ modmenu_version=9.0.0-pre.1 cloth_version=13.0.114 junit_version=5.10.1 +assertj_version=3.25.1 mockito_version=5.8.0 \ No newline at end of file From 68dd5560e82a95a91388864bac7f3a77643f16f6 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 12 Jan 2024 15:57:19 +0000 Subject: [PATCH 08/28] Add JUnit Parameterized Tests dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index ac0ad5c5..48305838 100644 --- a/build.gradle +++ b/build.gradle @@ -50,6 +50,7 @@ subprojects { testImplementation(platform("org.junit:junit-bom:${rootProject.junit_version}")) testImplementation("org.junit.jupiter:junit-jupiter") + testImplementation("org.junit.jupiter:junit-jupiter-params") testImplementation "org.assertj:assertj-core:${rootProject.assertj_version}" testImplementation "org.mockito:mockito-core:${rootProject.mockito_version}" testImplementation "org.mockito:mockito-junit-jupiter:${rootProject.mockito_version}" From c73815aaf0415d2534740d1004b6b38acb22ecc1 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 12 Jan 2024 16:53:59 +0000 Subject: [PATCH 09/28] Add a reflection util --- .../net/xolt/freecam/test/util/TestUtils.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 common/src/test/java/net/xolt/freecam/test/util/TestUtils.java diff --git a/common/src/test/java/net/xolt/freecam/test/util/TestUtils.java b/common/src/test/java/net/xolt/freecam/test/util/TestUtils.java new file mode 100644 index 00000000..869fa1e0 --- /dev/null +++ b/common/src/test/java/net/xolt/freecam/test/util/TestUtils.java @@ -0,0 +1,32 @@ +package net.xolt.freecam.test.util; + +import java.lang.reflect.Field; +import java.lang.reflect.InaccessibleObjectException; + +public class TestUtils { + /** + * Get the value of an object's field using reflection. + * + * @param type The field type + * @param instance The object from which to get the field + * @param field The name of the field + * @param The field type + * @return the field's value + * @throws RuntimeException if anything goes wrong + */ + public static T getFieldValue(Class type, Object instance, String field) { + try { + Class instanceType = instance.getClass(); + Field declaredField = instanceType.getDeclaredField(field); + declaredField.setAccessible(true); + Object it = declaredField.get(instance); + return type.cast(it); + } catch (NoSuchFieldException + | IllegalAccessException + | InaccessibleObjectException + | SecurityException + | ClassCastException e) { + throw new RuntimeException(e); + } + } +} From 248911e81edf4c658009275432200f232f2c6774 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 12 Jan 2024 16:20:00 +0000 Subject: [PATCH 10/28] AssertJ setRotation test --- .../freecam/util/FreecamPositionTest.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index 17cee179..41031501 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -3,13 +3,17 @@ import net.minecraft.client.player.RemotePlayer; import net.xolt.freecam.test.extension.BootstrapMinecraft; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import static org.assertj.core.api.Assertions.assertThat; + @BootstrapMinecraft @ExtendWith(MockitoExtension.class) class FreecamPositionTest { @@ -26,12 +30,27 @@ void setUp() { void tearDown() { } - @Test - void setRotation() { - position.setRotation(10, 20); - Assertions.assertAll( - () -> Assertions.assertEquals(10, position.yaw), - () -> Assertions.assertEquals(20, position.pitch)); + @ParameterizedTest + @DisplayName("setRotation correctly sets yaw & pitch") + @ValueSource(floats = { -16.456f, 0, 10, 2.5f, 2000008896.546f }) + void setRotation_YawPitch(float number) { + final float constant = 10; + assertThat(position).isNotNull().satisfies( + position -> { + position.setRotation(number, constant); + assertThat(position).as("Yaw is set correctly").satisfies( + p -> assertThat(p.yaw).as("Yaw is set to (var) " + number).isEqualTo(number), + p -> assertThat(p.pitch).as("Pitch is set to (const) " + constant).isEqualTo(constant) + ); + }, + position -> { + position.setRotation(constant, number); + assertThat(position).as("Pitch is set correctly").satisfies( + p -> assertThat(p.yaw).as("Yaw is set to (const) " + constant).isEqualTo(constant), + p -> assertThat(p.pitch).as("Pitch is set to (var) " + number).isEqualTo(number) + ); + } + ); } @Test From f45294202551ef35668a3cc233bd209e9239d195 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 12 Jan 2024 16:54:34 +0000 Subject: [PATCH 11/28] Test quaternion is updated by setRotation --- .../freecam/util/FreecamPositionTest.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index 41031501..6c3cd243 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -2,6 +2,7 @@ import net.minecraft.client.player.RemotePlayer; import net.xolt.freecam.test.extension.BootstrapMinecraft; +import org.joml.Quaternionf; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -12,6 +13,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import static net.xolt.freecam.test.util.TestUtils.getFieldValue; import static org.assertj.core.api.Assertions.assertThat; @BootstrapMinecraft @@ -53,6 +55,40 @@ void setRotation_YawPitch(float number) { ); } + @Test + @DisplayName("setRotation correctly updates quaternion") + void setRotation_Quaternion() { + Quaternionf initialRotation = getFieldValue(Quaternionf.class, position, "rotation"); + assertThat(initialRotation).as("Initially all zeros").satisfies( + rotation -> assertThat(rotation.x).as("x is correct").isEqualTo(0), + rotation -> assertThat(rotation.y).as("y is correct").isEqualTo(0), + rotation -> assertThat(rotation.z).as("z is correct").isEqualTo(0), + rotation -> assertThat(rotation.w).as("w is correct").isEqualTo(1) + ); + position.setRotation(10, 20); + Quaternionf rotationAfterTenTwenty = getFieldValue(Quaternionf.class, position, "rotation"); + assertThat(rotationAfterTenTwenty).as("Mutated correctly").satisfies( + // Magic numbers obtained from working implementation + rotation -> assertThat(rotation.x).as("x is correct").isEqualTo(0.1729874f), + rotation -> assertThat(rotation.y).as("y is correct").isEqualTo(-0.08583164f), + rotation -> assertThat(rotation.z).as("z is correct").isEqualTo(0.015134435f), + rotation -> assertThat(rotation.w).as("w is correct").isEqualTo(0.98106027f) + ); + position.setRotation(100, 200); + Quaternionf rotationAfterHundredTwoHundred = getFieldValue(Quaternionf.class, position, "rotation"); + assertThat(rotationAfterHundredTwoHundred).as("Mutated correctly").satisfies( + // Magic numbers obtained from working implementation + rotation -> assertThat(rotation.x).as("x is correct").isEqualTo(0.63302225f), + rotation -> assertThat(rotation.y).as("y is correct").isEqualTo(0.13302235f), + rotation -> assertThat(rotation.z).as("z is correct").isEqualTo(0.7544065f), + rotation -> assertThat(rotation.w).as("w is correct").isEqualTo(-0.11161902f) + ); + position.setRotation(0, 0); + Quaternionf rotationReset = getFieldValue(Quaternionf.class, position, "rotation"); + assertThat(rotationReset).as("Reset matches initial value").isEqualTo(initialRotation); + + } + @Test void mirrorRotation() { } From e068b40f2f84f5cba88d6084ae374869470e2dd8 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 10:10:40 +0000 Subject: [PATCH 12/28] Add EnableMockito annotation --- .../xolt/freecam/test/extension/EnableMockito.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 common/src/test/java/net/xolt/freecam/test/extension/EnableMockito.java diff --git a/common/src/test/java/net/xolt/freecam/test/extension/EnableMockito.java b/common/src/test/java/net/xolt/freecam/test/extension/EnableMockito.java new file mode 100644 index 00000000..4eea305a --- /dev/null +++ b/common/src/test/java/net/xolt/freecam/test/extension/EnableMockito.java @@ -0,0 +1,14 @@ +package net.xolt.freecam.test.extension; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@ExtendWith(MockitoExtension.class) +public @interface EnableMockito {} From ec2adb2c2ca7bff08fc9ad2f60f9c84fdff8d8fe Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 10:10:47 +0000 Subject: [PATCH 13/28] Use EnableMockito annotation --- .../test/java/net/xolt/freecam/util/FreecamPositionTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index 6c3cd243..352acac5 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -2,22 +2,21 @@ import net.minecraft.client.player.RemotePlayer; import net.xolt.freecam.test.extension.BootstrapMinecraft; +import net.xolt.freecam.test.extension.EnableMockito; import org.joml.Quaternionf; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import static net.xolt.freecam.test.util.TestUtils.getFieldValue; import static org.assertj.core.api.Assertions.assertThat; +@EnableMockito @BootstrapMinecraft -@ExtendWith(MockitoExtension.class) class FreecamPositionTest { @Mock RemotePlayer player; From e2d915d7d92db1576da10aa7a7a78599c798c520 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 10:37:11 +0000 Subject: [PATCH 14/28] Move testing utils to separate project --- build.gradle | 4 ++++ settings.gradle | 1 + test-utils/build.gradle | 11 +++++++++++ .../testing}/extension/BootstrapMinecraft.java | 2 +- .../extension/BootstrapMinecraftExtension.java | 2 +- .../freecam/testing}/extension/EnableMockito.java | 2 +- .../net/xolt/freecam/testing}/util/TestUtils.java | 2 +- 7 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 test-utils/build.gradle rename {common/src/test/java/net/xolt/freecam/test => test-utils/src/main/java/net/xolt/freecam/testing}/extension/BootstrapMinecraft.java (90%) rename {common/src/test/java/net/xolt/freecam/test => test-utils/src/main/java/net/xolt/freecam/testing}/extension/BootstrapMinecraftExtension.java (91%) rename {common/src/test/java/net/xolt/freecam/test => test-utils/src/main/java/net/xolt/freecam/testing}/extension/EnableMockito.java (90%) rename {common/src/test/java/net/xolt/freecam/test => test-utils/src/main/java/net/xolt/freecam/testing}/util/TestUtils.java (96%) diff --git a/build.gradle b/build.gradle index 48305838..9a2c2d4e 100644 --- a/build.gradle +++ b/build.gradle @@ -54,6 +54,10 @@ subprojects { testImplementation "org.assertj:assertj-core:${rootProject.assertj_version}" testImplementation "org.mockito:mockito-core:${rootProject.mockito_version}" testImplementation "org.mockito:mockito-junit-jupiter:${rootProject.mockito_version}" + + if (project.name != "test-util") { + dependencies.testImplementation dependencies.project(path: ":test-utils", configuration: "namedElements") + } } test { diff --git a/settings.gradle b/settings.gradle index b27a6722..4f493a7c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,7 @@ include("common") include("fabric") include("neoforge") include("metadata") +include("test-utils") include("variant", "variant:api", "variant:normal", "variant:modrinth") rootProject.name = "freecam" diff --git a/test-utils/build.gradle b/test-utils/build.gradle new file mode 100644 index 00000000..8f2fff56 --- /dev/null +++ b/test-utils/build.gradle @@ -0,0 +1,11 @@ +architectury { + common(rootProject.enabled_platforms.split(',')) +} + +dependencies { + // Needed for Environment annotation + modCompileOnly "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + implementation(platform("org.junit:junit-bom:${rootProject.junit_version}")) + implementation("org.junit.jupiter:junit-jupiter-api") + implementation "org.mockito:mockito-junit-jupiter:${rootProject.mockito_version}" +} diff --git a/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraft.java b/test-utils/src/main/java/net/xolt/freecam/testing/extension/BootstrapMinecraft.java similarity index 90% rename from common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraft.java rename to test-utils/src/main/java/net/xolt/freecam/testing/extension/BootstrapMinecraft.java index 9d13b5ed..b80e7322 100644 --- a/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraft.java +++ b/test-utils/src/main/java/net/xolt/freecam/testing/extension/BootstrapMinecraft.java @@ -1,4 +1,4 @@ -package net.xolt.freecam.test.extension; +package net.xolt.freecam.testing.extension; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraftExtension.java b/test-utils/src/main/java/net/xolt/freecam/testing/extension/BootstrapMinecraftExtension.java similarity index 91% rename from common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraftExtension.java rename to test-utils/src/main/java/net/xolt/freecam/testing/extension/BootstrapMinecraftExtension.java index b6a36253..d804ae93 100644 --- a/common/src/test/java/net/xolt/freecam/test/extension/BootstrapMinecraftExtension.java +++ b/test-utils/src/main/java/net/xolt/freecam/testing/extension/BootstrapMinecraftExtension.java @@ -1,4 +1,4 @@ -package net.xolt.freecam.test.extension; +package net.xolt.freecam.testing.extension; import net.minecraft.SharedConstants; import net.minecraft.server.Bootstrap; diff --git a/common/src/test/java/net/xolt/freecam/test/extension/EnableMockito.java b/test-utils/src/main/java/net/xolt/freecam/testing/extension/EnableMockito.java similarity index 90% rename from common/src/test/java/net/xolt/freecam/test/extension/EnableMockito.java rename to test-utils/src/main/java/net/xolt/freecam/testing/extension/EnableMockito.java index 4eea305a..ae120a88 100644 --- a/common/src/test/java/net/xolt/freecam/test/extension/EnableMockito.java +++ b/test-utils/src/main/java/net/xolt/freecam/testing/extension/EnableMockito.java @@ -1,4 +1,4 @@ -package net.xolt.freecam.test.extension; +package net.xolt.freecam.testing.extension; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; diff --git a/common/src/test/java/net/xolt/freecam/test/util/TestUtils.java b/test-utils/src/main/java/net/xolt/freecam/testing/util/TestUtils.java similarity index 96% rename from common/src/test/java/net/xolt/freecam/test/util/TestUtils.java rename to test-utils/src/main/java/net/xolt/freecam/testing/util/TestUtils.java index 869fa1e0..e616fd12 100644 --- a/common/src/test/java/net/xolt/freecam/test/util/TestUtils.java +++ b/test-utils/src/main/java/net/xolt/freecam/testing/util/TestUtils.java @@ -1,4 +1,4 @@ -package net.xolt.freecam.test.util; +package net.xolt.freecam.testing.util; import java.lang.reflect.Field; import java.lang.reflect.InaccessibleObjectException; From 6b507b7fa79fa93d4d1d7d09198bc47339c31080 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 10:37:31 +0000 Subject: [PATCH 15/28] Fix testing utils imports --- .../java/net/xolt/freecam/util/FreecamPositionTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index 352acac5..77c4f133 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -1,8 +1,8 @@ package net.xolt.freecam.util; import net.minecraft.client.player.RemotePlayer; -import net.xolt.freecam.test.extension.BootstrapMinecraft; -import net.xolt.freecam.test.extension.EnableMockito; +import net.xolt.freecam.testing.extension.BootstrapMinecraft; +import net.xolt.freecam.testing.extension.EnableMockito; import org.joml.Quaternionf; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -12,7 +12,7 @@ import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; -import static net.xolt.freecam.test.util.TestUtils.getFieldValue; +import static net.xolt.freecam.testing.util.TestUtils.getFieldValue; import static org.assertj.core.api.Assertions.assertThat; @EnableMockito From 8b100b88db80f6872d07c4fdafcb030933bdf828 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 10:53:10 +0000 Subject: [PATCH 16/28] Enable fabric-specific tests --- fabric/build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fabric/build.gradle b/fabric/build.gradle index c65c6a57..87b48dd4 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -37,6 +37,9 @@ dependencies { shadowCommon project(path: ":common", configuration: "transformProductionFabric") shadowCommon project(":variant:api") + + // Use fabric's Knot classloader in tests + testImplementation "net.fabricmc:fabric-loader-junit:${rootProject.fabric_loader_version}" } variants.each { variant -> @@ -58,6 +61,15 @@ variants.each { variant -> dependencies.add(set.implementationConfigurationName, dependencies.project(path: ":variant:${variant}", configuration: "namedElements")) dependencies.add(shadowConfig.name, dependencies.project(path: ":variant:${variant}", configuration: "transformProductionFabric")) + // Add the normal variant to the test classpath + // TODO consider testing other variants too + sourceSets { + if (variant == "normal") { + test.compileClasspath += set.compileClasspath + test.runtimeClasspath += set.runtimeClasspath + } + } + // Configure/create a run config def run if (variant == "normal") { From 8450d329fa838a653918ecd1172f7ffb3264021f Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 10:53:31 +0000 Subject: [PATCH 17/28] Audit mixin in fabric environment --- .../net/xolt/freecam/environment/MixinTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 fabric/src/test/java/net/xolt/freecam/environment/MixinTest.java diff --git a/fabric/src/test/java/net/xolt/freecam/environment/MixinTest.java b/fabric/src/test/java/net/xolt/freecam/environment/MixinTest.java new file mode 100644 index 00000000..bc855cb6 --- /dev/null +++ b/fabric/src/test/java/net/xolt/freecam/environment/MixinTest.java @@ -0,0 +1,15 @@ +package net.xolt.freecam.environment; + +import net.xolt.freecam.testing.extension.BootstrapMinecraft; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.spongepowered.asm.mixin.MixinEnvironment; + +@BootstrapMinecraft +class MixinTest { + @Test + @DisplayName("Audit mixin environment") + void mixinEnvironmentAudit() { + MixinEnvironment.getCurrentEnvironment().audit(); + } +} From 1563829400352de0c01c64188f2a0cfb71562740 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 11:08:44 +0000 Subject: [PATCH 18/28] Validate Minecraft in fabric environment --- .../xolt/freecam/environment/BootstrapTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 fabric/src/test/java/net/xolt/freecam/environment/BootstrapTest.java diff --git a/fabric/src/test/java/net/xolt/freecam/environment/BootstrapTest.java b/fabric/src/test/java/net/xolt/freecam/environment/BootstrapTest.java new file mode 100644 index 00000000..92ca2aad --- /dev/null +++ b/fabric/src/test/java/net/xolt/freecam/environment/BootstrapTest.java @@ -0,0 +1,15 @@ +package net.xolt.freecam.environment; + +import net.minecraft.server.Bootstrap; +import net.xolt.freecam.testing.extension.BootstrapMinecraft; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@BootstrapMinecraft +class BootstrapTest { + @Test + @DisplayName("Validate Minecraft is bootstrapped") + void validateBootstrap() { + Bootstrap.validate(); + } +} From 357f0ae36e6d2b2333358c828f3a16261bc0d4c9 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 12:54:44 +0000 Subject: [PATCH 19/28] Test moveForward() together with setRotation() --- .../freecam/util/FreecamPositionTest.java | 106 ++++++++++-------- 1 file changed, 62 insertions(+), 44 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index 77c4f133..2c498e59 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -3,16 +3,15 @@ import net.minecraft.client.player.RemotePlayer; import net.xolt.freecam.testing.extension.BootstrapMinecraft; import net.xolt.freecam.testing.extension.EnableMockito; -import org.joml.Quaternionf; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; -import static net.xolt.freecam.testing.util.TestUtils.getFieldValue; import static org.assertj.core.api.Assertions.assertThat; @EnableMockito @@ -22,6 +21,10 @@ class FreecamPositionTest { @Mock RemotePlayer player; private FreecamPosition position; + static double[] distances() { + return new double[] { 1, -1, 2_000_000_001, 0.00456789, -0.0000445646456456060456, 2.5 }; + } + @BeforeEach void setUp() { position = new FreecamPosition(player); @@ -31,6 +34,63 @@ void setUp() { void tearDown() { } + @ParameterizedTest + @MethodSource("distances") + @DisplayName("Moves forward on x axis") + void moveForward_x(double distance) { + float yaw = -90; + float pitch = 0; + + double x = position.x; + double y = position.y; + double z = position.z; + + position.setRotation(yaw, pitch); + position.moveForward(distance); + + assertThat(position.x).as("x increased by " + distance).isEqualTo(x + distance); + assertThat(position.y).as("y is unchanged").isEqualTo(y); + assertThat(position.z).as("z is unchanged").isEqualTo(z); + } + + @ParameterizedTest + @MethodSource("distances") + @DisplayName("Moves forward on y axis") + void moveForward_y(double distance) { + float yaw = 0; + float pitch = -90; + + double x = position.x; + double y = position.y; + double z = position.z; + + position.setRotation(yaw, pitch); + position.moveForward(distance); + + assertThat(position.x).as("x is unchanged").isEqualTo(x); + assertThat(position.y).as("y increased by " + distance).isEqualTo(y + distance); + assertThat(position.z).as("z is unchanged").isEqualTo(z); + } + + @ParameterizedTest + @MethodSource("distances") + @DisplayName("Moves forward on z axis") + void moveForward_z(double distance) { + float yaw = 0; + float pitch = 0; + + double x = position.x; + double y = position.y; + double z = position.z; + + position.setRotation(yaw, pitch); + position.moveForward(distance); + + assertThat(position.x).as("x is unchanged").isEqualTo(x); + assertThat(position.y).as("y is unchanged").isEqualTo(y); + assertThat(position.z).as("z increased by " + distance).isEqualTo(z + distance); + } + @ParameterizedTest @DisplayName("setRotation correctly sets yaw & pitch") @ValueSource(floats = { -16.456f, 0, 10, 2.5f, 2000008896.546f }) @@ -54,52 +114,10 @@ void setRotation_YawPitch(float number) { ); } - @Test - @DisplayName("setRotation correctly updates quaternion") - void setRotation_Quaternion() { - Quaternionf initialRotation = getFieldValue(Quaternionf.class, position, "rotation"); - assertThat(initialRotation).as("Initially all zeros").satisfies( - rotation -> assertThat(rotation.x).as("x is correct").isEqualTo(0), - rotation -> assertThat(rotation.y).as("y is correct").isEqualTo(0), - rotation -> assertThat(rotation.z).as("z is correct").isEqualTo(0), - rotation -> assertThat(rotation.w).as("w is correct").isEqualTo(1) - ); - position.setRotation(10, 20); - Quaternionf rotationAfterTenTwenty = getFieldValue(Quaternionf.class, position, "rotation"); - assertThat(rotationAfterTenTwenty).as("Mutated correctly").satisfies( - // Magic numbers obtained from working implementation - rotation -> assertThat(rotation.x).as("x is correct").isEqualTo(0.1729874f), - rotation -> assertThat(rotation.y).as("y is correct").isEqualTo(-0.08583164f), - rotation -> assertThat(rotation.z).as("z is correct").isEqualTo(0.015134435f), - rotation -> assertThat(rotation.w).as("w is correct").isEqualTo(0.98106027f) - ); - position.setRotation(100, 200); - Quaternionf rotationAfterHundredTwoHundred = getFieldValue(Quaternionf.class, position, "rotation"); - assertThat(rotationAfterHundredTwoHundred).as("Mutated correctly").satisfies( - // Magic numbers obtained from working implementation - rotation -> assertThat(rotation.x).as("x is correct").isEqualTo(0.63302225f), - rotation -> assertThat(rotation.y).as("y is correct").isEqualTo(0.13302235f), - rotation -> assertThat(rotation.z).as("z is correct").isEqualTo(0.7544065f), - rotation -> assertThat(rotation.w).as("w is correct").isEqualTo(-0.11161902f) - ); - position.setRotation(0, 0); - Quaternionf rotationReset = getFieldValue(Quaternionf.class, position, "rotation"); - assertThat(rotationReset).as("Reset matches initial value").isEqualTo(initialRotation); - - } - @Test void mirrorRotation() { } - @Test - void moveForward() { - } - - @Test - void move() { - } - @Test void getChunkPos() { } From b2a3c0a3ebd60f76dcc5d015ceeedc74590fe524 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 14:14:21 +0000 Subject: [PATCH 20/28] Add constructor test for swimming position --- .../freecam/util/FreecamPositionTest.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index 2c498e59..577c30cf 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -1,6 +1,11 @@ package net.xolt.freecam.util; +import com.mojang.authlib.GameProfile; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.RemotePlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Pose; import net.xolt.freecam.testing.extension.BootstrapMinecraft; import net.xolt.freecam.testing.extension.EnableMockito; import org.junit.jupiter.api.AfterEach; @@ -8,17 +13,24 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.withPrecision; +import static org.mockito.Mockito.when; @EnableMockito @BootstrapMinecraft class FreecamPositionTest { - @Mock RemotePlayer player; + @Mock ClientLevel level; + @Mock GameProfile profile; + Entity entity; private FreecamPosition position; static double[] distances() { @@ -27,13 +39,30 @@ static double[] distances() { @BeforeEach void setUp() { - position = new FreecamPosition(player); + when(profile.getId()).thenReturn(UUID.fromString("00000000-0000-0000-0000-000000000000")); + when(level.getSharedSpawnPos()).thenReturn(BlockPos.ZERO); + when(level.getSharedSpawnAngle()).thenReturn(0f); + entity = new RemotePlayer(level, profile); + position = new FreecamPosition(entity); } @AfterEach void tearDown() { } + @ParameterizedTest + @EnumSource(Pose.class) + @DisplayName("Adjust entity position for pose") + void init_standing(Pose pose) { + entity.setPose(pose); + double diff = entity.getEyeHeight(pose) - entity.getEyeHeight(Pose.SWIMMING); + FreecamPosition swimPos = new FreecamPosition(entity); + + assertThat(swimPos.x).as("Correct x").isEqualTo(entity.getX()); + assertThat(swimPos.y).as("y is %01.2f higher".formatted(diff)).isEqualTo(entity.getY() + diff, withPrecision(0.0000004)); + assertThat(swimPos.z).as("Correct z").isEqualTo(entity.getZ()); + } + @ParameterizedTest @MethodSource("distances") @DisplayName("Moves forward on x axis") From ff74175fc1850da01eea5ed2b8eee10b04c95079 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 15:39:26 +0000 Subject: [PATCH 21/28] Minor improvements --- .../xolt/freecam/util/FreecamPositionTest.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index 577c30cf..ea408bc9 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -16,22 +16,20 @@ import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.Mock; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.withPrecision; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @EnableMockito @BootstrapMinecraft class FreecamPositionTest { - @Mock ClientLevel level; - @Mock GameProfile profile; Entity entity; - private FreecamPosition position; + FreecamPosition position; static double[] distances() { return new double[] { 1, -1, 2_000_000_001, 0.00456789, -0.0000445646456456060456, 2.5 }; @@ -39,9 +37,10 @@ static double[] distances() { @BeforeEach void setUp() { - when(profile.getId()).thenReturn(UUID.fromString("00000000-0000-0000-0000-000000000000")); + ClientLevel level = mock(ClientLevel.class); when(level.getSharedSpawnPos()).thenReturn(BlockPos.ZERO); when(level.getSharedSpawnAngle()).thenReturn(0f); + GameProfile profile = new GameProfile(new UUID(0, 0), "TestPlayer"); entity = new RemotePlayer(level, profile); position = new FreecamPosition(entity); } @@ -53,14 +52,14 @@ void tearDown() { @ParameterizedTest @EnumSource(Pose.class) @DisplayName("Adjust entity position for pose") - void init_standing(Pose pose) { + void init_pose(Pose pose) { entity.setPose(pose); double diff = entity.getEyeHeight(pose) - entity.getEyeHeight(Pose.SWIMMING); FreecamPosition swimPos = new FreecamPosition(entity); - assertThat(swimPos.x).as("Correct x").isEqualTo(entity.getX()); - assertThat(swimPos.y).as("y is %01.2f higher".formatted(diff)).isEqualTo(entity.getY() + diff, withPrecision(0.0000004)); - assertThat(swimPos.z).as("Correct z").isEqualTo(entity.getZ()); + assertThat(swimPos.x).as("x is %01.2f".formatted(entity.getX())).isEqualTo(entity.getX()); + assertThat(swimPos.y).as("y is %01.2f higher than %01.2f".formatted(diff, entity.getY())).isEqualTo(entity.getY() + diff, withPrecision(0.0000004)); + assertThat(swimPos.z).as("z is %01.2f".formatted(entity.getZ())).isEqualTo(entity.getZ()); } @ParameterizedTest From bc48ecae11ef4bfd840949efc8f87f46c8aa6682 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sun, 14 Jan 2024 15:41:54 +0000 Subject: [PATCH 22/28] ci: new build workflow (cherry picked from commit 05b98608e5ad3ded2fe15569e9141619a6f7aae6) --- .github/workflows/build.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..5b9238c2 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,31 @@ +name: Gradle build + +on: + push: + branches: &branches + - 'main' + - '1.16' + - '1.17' + - '1.18' + - '1.19' + pull_request: + branches: *branches + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up JDK + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: microsoft + - name: Build with Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: build + # TODO: run gradle test From 41e7fcb8dbf44daec2def75ce57c127f038a7058 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 17:17:56 +0000 Subject: [PATCH 23/28] ci: run tests in main workflow --- .github/workflows/{build.yml => main.yml} | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) rename .github/workflows/{build.yml => main.yml} (63%) diff --git a/.github/workflows/build.yml b/.github/workflows/main.yml similarity index 63% rename from .github/workflows/build.yml rename to .github/workflows/main.yml index 5b9238c2..f4ce81eb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: Gradle build +name: Gradle (build & test) on: push: @@ -15,7 +15,7 @@ permissions: contents: read jobs: - build: + build_and_test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -24,8 +24,12 @@ jobs: with: java-version: '17' distribution: microsoft - - name: Build with Gradle + - name: Build uses: gradle/gradle-build-action@v2 with: arguments: build - # TODO: run gradle test + - name: Test + uses: gradle/gradle-build-action@v2 + with: + # We could run `check` instead, but we may want to add checks we don't want to use in CI...? + arguments: test From 953678b306d325178f221f2af82a28fb584bd65b Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 17:18:11 +0000 Subject: [PATCH 24/28] ci: add status badge to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ab11eac6..dac141b9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Freecam +![CI](https://github.com/MinecraftFreecam/Freecam/actions/workflows/main.yml/badge.svg?event=push) [![Crowdin](https://badges.crowdin.net/freecam/localized.svg)](https://crowdin.com/project/freecam) This mod allows you to control your camera separately from your player. While it is enabled, you can fly around and travel through blocks within your render distance. Disabling it will restore you to your original position. This can be useful for quickly inspecting builds and exploring your world. From e42119676b7a2b3f14bcf69a84bc20fbb1e62eaa Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 19:33:55 +0000 Subject: [PATCH 25/28] Add constructor rotation test --- .../xolt/freecam/util/FreecamPositionTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index ea408bc9..cfcd4281 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Pose; +import net.minecraft.world.phys.Vec2; import net.xolt.freecam.testing.extension.BootstrapMinecraft; import net.xolt.freecam.testing.extension.EnableMockito; import org.junit.jupiter.api.AfterEach; @@ -35,6 +36,10 @@ static double[] distances() { return new double[] { 1, -1, 2_000_000_001, 0.00456789, -0.0000445646456456060456, 2.5 }; } + static Vec2[] rotations() { + return new Vec2[] { Vec2.ZERO, Vec2.MIN, Vec2.MAX, Vec2.UNIT_X, Vec2.UNIT_Y, Vec2.NEG_UNIT_X, Vec2.NEG_UNIT_Y }; + } + @BeforeEach void setUp() { ClientLevel level = mock(ClientLevel.class); @@ -62,6 +67,18 @@ void init_pose(Pose pose) { assertThat(swimPos.z).as("z is %01.2f".formatted(entity.getZ())).isEqualTo(entity.getZ()); } + @ParameterizedTest + @MethodSource("rotations") + @DisplayName("Uses entity rotation") + void init_rotation(Vec2 rotation) { + entity.setXRot(rotation.x); + entity.setYRot(rotation.y); + FreecamPosition rotatedPos = new FreecamPosition(entity); + + assertThat(rotatedPos.yaw).as("yaw is %01.2f".formatted(rotation.y)).isEqualTo(rotation.y); + assertThat(rotatedPos.pitch).as("pitch is %01.2f".formatted(rotation.x)).isEqualTo(rotation.x); + } + @ParameterizedTest @MethodSource("distances") @DisplayName("Moves forward on x axis") From 42b7581f069a61aad791e10b4b311dcd4f2c4bc6 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 19:36:13 +0000 Subject: [PATCH 26/28] fixup! Add constructor test for swimming position --- .../test/java/net/xolt/freecam/util/FreecamPositionTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index cfcd4281..f239de97 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -56,8 +56,8 @@ void tearDown() { @ParameterizedTest @EnumSource(Pose.class) - @DisplayName("Adjust entity position for pose") - void init_pose(Pose pose) { + @DisplayName("Use entity position, adjusted for pose") + void init_position(Pose pose) { entity.setPose(pose); double diff = entity.getEyeHeight(pose) - entity.getEyeHeight(Pose.SWIMMING); FreecamPosition swimPos = new FreecamPosition(entity); From e4e2c18b562f7ad4b0fefae16e27a71ae29ced4f Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 19:54:15 +0000 Subject: [PATCH 27/28] Test moving position after mirroring --- .../freecam/util/FreecamPositionTest.java | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index f239de97..bcca2744 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -96,6 +96,14 @@ void moveForward_x(double distance) { assertThat(position.x).as("x increased by " + distance).isEqualTo(x + distance); assertThat(position.y).as("y is unchanged").isEqualTo(y); assertThat(position.z).as("z is unchanged").isEqualTo(z); + + // Moving the same distance after a mirror should revert + position.mirrorRotation(); + position.moveForward(distance); + + assertThat(position.x).as("x is reverted").isEqualTo(x); + assertThat(position.y).as("y is unchanged").isEqualTo(y); + assertThat(position.z).as("z is unchanged").isEqualTo(z); } @ParameterizedTest @@ -115,6 +123,14 @@ void moveForward_y(double distance) { assertThat(position.x).as("x is unchanged").isEqualTo(x); assertThat(position.y).as("y increased by " + distance).isEqualTo(y + distance); assertThat(position.z).as("z is unchanged").isEqualTo(z); + + // Moving the same distance after a mirror should revert + position.mirrorRotation(); + position.moveForward(distance); + + assertThat(position.x).as("x is unchanged").isEqualTo(x); + assertThat(position.y).as("y is reverted").isEqualTo(y); + assertThat(position.z).as("z is unchanged").isEqualTo(z); } @ParameterizedTest @@ -134,6 +150,14 @@ void moveForward_z(double distance) { assertThat(position.x).as("x is unchanged").isEqualTo(x); assertThat(position.y).as("y is unchanged").isEqualTo(y); assertThat(position.z).as("z increased by " + distance).isEqualTo(z + distance); + + // Moving the same distance after a mirror should revert + position.mirrorRotation(); + position.moveForward(distance); + + assertThat(position.x).as("x is unchanged").isEqualTo(x); + assertThat(position.y).as("y is unchanged").isEqualTo(y); + assertThat(position.z).as("z is reverted").isEqualTo(z); } @ParameterizedTest @@ -159,10 +183,6 @@ void setRotation_YawPitch(float number) { ); } - @Test - void mirrorRotation() { - } - @Test void getChunkPos() { } From e6fa497657899759baafabe1783e252a0355e840 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 19 Jan 2024 20:05:59 +0000 Subject: [PATCH 28/28] Test chunk pos --- .../freecam/util/FreecamPositionTest.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java index bcca2744..4614ffa7 100644 --- a/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java +++ b/common/src/test/java/net/xolt/freecam/util/FreecamPositionTest.java @@ -6,13 +6,14 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Pose; +import net.minecraft.world.level.ChunkPos; import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; import net.xolt.freecam.testing.extension.BootstrapMinecraft; import net.xolt.freecam.testing.extension.EnableMockito; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; @@ -40,6 +41,10 @@ static Vec2[] rotations() { return new Vec2[] { Vec2.ZERO, Vec2.MIN, Vec2.MAX, Vec2.UNIT_X, Vec2.UNIT_Y, Vec2.NEG_UNIT_X, Vec2.NEG_UNIT_Y }; } + static Vec3[] positions() { + return new Vec3[] { Vec3.ZERO, new Vec3(1, 1, 1), new Vec3(1000, 100, 10) }; + } + @BeforeEach void setUp() { ClientLevel level = mock(ClientLevel.class); @@ -183,7 +188,18 @@ void setRotation_YawPitch(float number) { ); } - @Test - void getChunkPos() { + @ParameterizedTest + @MethodSource("positions") + @DisplayName("ChunkPos should be 16 times smaller than position") + void chunkPos(Vec3 pos) { + position.x = pos.x; + position.y = pos.y; + position.z = pos.z; + // Should be 16 times smaller than x y z position, rounded down + int x = (int) (pos.x / 16); + int z = (int) (pos.z / 16); + ChunkPos chunkPos = position.getChunkPos(); + assertThat(chunkPos.x).isEqualTo(x); + assertThat(chunkPos.z).isEqualTo(z); } } \ No newline at end of file