From 873d9df2af6526e3044f3f98b936952f0ce398ea Mon Sep 17 00:00:00 2001 From: darkweird Date: Fri, 12 Nov 2021 10:08:03 +0300 Subject: [PATCH 1/8] feature(WorkspaceValidationTests): add possible to create workspace-wide tests --- .gitignore | 1 + facades/WorkspaceValidation/.gitignore | 11 +++ facades/WorkspaceValidation/build.gradle | 76 +++++++++++++++++++ .../validation/BehaviorsLoadingTest.java | 67 ++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 facades/WorkspaceValidation/.gitignore create mode 100644 facades/WorkspaceValidation/build.gradle create mode 100644 facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/BehaviorsLoadingTest.java diff --git a/.gitignore b/.gitignore index c1af677b996..4825b0aa7be 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ extensions /facades/* !/facades/PC !/facades/TeraEd +!/facades/WorkspaceValidation !/facades/subprojects.gradle /modules/* !/modules/subprojects.gradle diff --git a/facades/WorkspaceValidation/.gitignore b/facades/WorkspaceValidation/.gitignore new file mode 100644 index 00000000000..7263b6ee479 --- /dev/null +++ b/facades/WorkspaceValidation/.gitignore @@ -0,0 +1,11 @@ +# Boo eclipse! - every eclipse project needs its own .gitignore file + +# Ignore Eclipse +/.checkstyle +/.project +/.classpath +/.settings/ +/bin/ + +# Ignore gradle +/build/ diff --git a/facades/WorkspaceValidation/build.gradle b/facades/WorkspaceValidation/build.gradle new file mode 100644 index 00000000000..e311564de44 --- /dev/null +++ b/facades/WorkspaceValidation/build.gradle @@ -0,0 +1,76 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +// The Editor facade is responsible for the (shader) editor - a plain Java application runnable on PCs + +// Grab all the common stuff like plugins to use, artifact repositories, code analysis config +apply from: "$rootDir/config/gradle/publish.gradle" + +// Base the engine tests on the same version number as the engine +version = project(':engine').version +println "TeraEd VERSION: $version" + +// Jenkins-Artifactory integration catches on to this as part of the Maven-type descriptor +group = 'org.terasology.facades' + +sourceSets { + // Adjust output path (changed with the Gradle 6 upgrade, this puts it back) + main.java.outputDir = new File("$buildDir/classes") + test.java.outputDir = new File("$buildDir/testClasses") +} + +dependencies { + implementation project(':engine') + implementation "org.terasology:reflections:0.9.12-MB" + + implementation(platform(project(":modules"))) +// // For the "natives" configuration make it depend on the native files from LWJGL +// implementation platform("org.lwjgl:lwjgl-bom:$LwjglVersion") +// ["natives-linux", "natives-windows", "natives-macos"].forEach { +// implementation "org.lwjgl:lwjgl::$it" +// implementation "org.lwjgl:lwjgl-assimp::$it" +// implementation "org.lwjgl:lwjgl-glfw::$it" +// implementation "org.lwjgl:lwjgl-openal::$it" +// implementation "org.lwjgl:lwjgl-opengl::$it" +// implementation "org.lwjgl:lwjgl-stb::$it" +// } + + implementation(group: 'com.google.guava', name: 'guava', version: '30.1-jre') + + implementation(project(":subsystems:DiscordRPC")) + implementation(project(":subsystems:TypeHandlerLibrary")) + + implementation(group: 'org.lwjglx', name: 'lwjgl3-awt', version: '0.1.7') { + exclude group: 'org.lwjgl', module: '' + } + + // Test lib dependencies + implementation(platform("org.junit:junit-bom:5.8.1")) { + // junit-bom will set version numbers for the other org.junit dependencies. + } + implementation("org.junit.jupiter:junit-jupiter-api") + implementation("org.junit.jupiter:junit-jupiter-params") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") + testImplementation('org.mockito:mockito-inline:3.12.4') +} + +test { +// dependsOn copyResourcesToClasses + dependsOn rootProject.extractNatives + + description("Runs all tests (slow)") + + systemProperty("junit.jupiter.execution.timeout.default", "4m") +} + + + +// Prep an IntelliJ module for the facade +idea { + module { + // Change around the output a bit + inheritOutputDirs = false + outputDir = file('build/classes') + testOutputDir = file('build/testClasses') + } +} diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/BehaviorsLoadingTest.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/BehaviorsLoadingTest.java new file mode 100644 index 00000000000..3cc925e67b3 --- /dev/null +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/BehaviorsLoadingTest.java @@ -0,0 +1,67 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.workspace.validation; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.terasology.engine.entitySystem.entity.EntityManager; +import org.terasology.engine.entitySystem.entity.EntityRef; +import org.terasology.engine.entitySystem.prefab.Prefab; +import org.terasology.engine.logic.behavior.BehaviorComponent; +import org.terasology.engine.logic.behavior.asset.BehaviorTree; +import org.terasology.engine.registry.In; +import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.gestalt.assets.management.AssetManager; +import org.terasology.moduletestingenvironment.MTEExtension; +import org.terasology.moduletestingenvironment.ModuleTestingHelper; +import org.terasology.moduletestingenvironment.extension.Dependencies; + +import java.util.stream.Stream; + +@Tag("Mte") +@ExtendWith(MTEExtension.class) +@Dependencies("JoshariasSurvival") +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class BehaviorsLoadingTest { + + @In + AssetManager assetManager; + @In + EntityManager entityManager; + + public Stream behaviors() { + return assetManager.getAvailableAssets(BehaviorTree.class) + .stream() + .map(Arguments::of); + } + + @ParameterizedTest + @MethodSource("behaviors") + void behaviorsTest(ResourceUrn urn) { + Assertions.assertDoesNotThrow(() -> + assetManager.getAsset(urn, BehaviorTree.class)); + } + + + public Stream prefabs() { + return assetManager.getAvailableAssets(Prefab.class) + .stream() + .map((p) -> assetManager.getAsset(p, Prefab.class).get()) + .filter((p) -> p.hasComponent(BehaviorComponent.class)) + .map(Arguments::of); + } + + @ParameterizedTest + @MethodSource("prefabs") + void prefabsTest(Prefab prefab, ModuleTestingHelper helper) { + EntityRef ref = entityManager.create(prefab); + Assertions.assertNotNull(ref.getComponent(BehaviorComponent.class).tree); + } + +} From 3a8c58e09cb58f8c3a7148a211b2febd211ee4f3 Mon Sep 17 00:00:00 2001 From: darkweird Date: Mon, 15 Nov 2021 11:08:55 +0300 Subject: [PATCH 2/8] feature(PathFinding-Behaviour): add module resolving tests. remove MTE-related test(for reworking) --- .../validation/BehaviorsLoadingTest.java | 67 ------------------- .../validation/WorkspaceBehaviorsTests.java | 41 ++++++++++++ .../WorkspaceModulesResolvingTests.java | 56 ++++++++++++++++ 3 files changed, 97 insertions(+), 67 deletions(-) delete mode 100644 facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/BehaviorsLoadingTest.java create mode 100644 facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java create mode 100644 facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceModulesResolvingTests.java diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/BehaviorsLoadingTest.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/BehaviorsLoadingTest.java deleted file mode 100644 index 3cc925e67b3..00000000000 --- a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/BehaviorsLoadingTest.java +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2021 The Terasology Foundation -// SPDX-License-Identifier: Apache-2.0 - -package org.terasology.workspace.validation; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.terasology.engine.entitySystem.entity.EntityManager; -import org.terasology.engine.entitySystem.entity.EntityRef; -import org.terasology.engine.entitySystem.prefab.Prefab; -import org.terasology.engine.logic.behavior.BehaviorComponent; -import org.terasology.engine.logic.behavior.asset.BehaviorTree; -import org.terasology.engine.registry.In; -import org.terasology.gestalt.assets.ResourceUrn; -import org.terasology.gestalt.assets.management.AssetManager; -import org.terasology.moduletestingenvironment.MTEExtension; -import org.terasology.moduletestingenvironment.ModuleTestingHelper; -import org.terasology.moduletestingenvironment.extension.Dependencies; - -import java.util.stream.Stream; - -@Tag("Mte") -@ExtendWith(MTEExtension.class) -@Dependencies("JoshariasSurvival") -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class BehaviorsLoadingTest { - - @In - AssetManager assetManager; - @In - EntityManager entityManager; - - public Stream behaviors() { - return assetManager.getAvailableAssets(BehaviorTree.class) - .stream() - .map(Arguments::of); - } - - @ParameterizedTest - @MethodSource("behaviors") - void behaviorsTest(ResourceUrn urn) { - Assertions.assertDoesNotThrow(() -> - assetManager.getAsset(urn, BehaviorTree.class)); - } - - - public Stream prefabs() { - return assetManager.getAvailableAssets(Prefab.class) - .stream() - .map((p) -> assetManager.getAsset(p, Prefab.class).get()) - .filter((p) -> p.hasComponent(BehaviorComponent.class)) - .map(Arguments::of); - } - - @ParameterizedTest - @MethodSource("prefabs") - void prefabsTest(Prefab prefab, ModuleTestingHelper helper) { - EntityRef ref = entityManager.create(prefab); - Assertions.assertNotNull(ref.getComponent(BehaviorComponent.class).tree); - } - -} diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java new file mode 100644 index 00000000000..ae5665b6ac2 --- /dev/null +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java @@ -0,0 +1,41 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.workspace.validation; + +import org.junit.jupiter.params.provider.Arguments; +import org.terasology.engine.core.module.ModuleManager; +import org.terasology.gestalt.assets.AssetType; +import org.terasology.gestalt.assets.management.AssetManager; +import org.terasology.gestalt.assets.management.AssetTypeManager; +import org.terasology.gestalt.assets.module.ModuleAwareAssetTypeManagerImpl; +import org.terasology.gestalt.naming.Name; + +import java.util.Set; +import java.util.stream.Stream; + +public class WorkspaceBehaviorsTests { + + public static Stream modulesAndModuleManager() { + System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); + ModuleManager temporary = new ModuleManager(""); + return temporary.getRegistry() + .getModuleIds() + .stream() + .map((name) -> Arguments.of(temporary, name)); + } + + public static Stream modulePairsAndModuleManager() { + System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); + ModuleManager temporary = new ModuleManager(""); + Set moduleIds = temporary.getRegistry() + .getModuleIds(); + return moduleIds + .stream() + .flatMap((name) -> moduleIds.stream().map((name2) -> Arguments.of(temporary, name, name2))); + } + + void behaviorTest() { + + } +} diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceModulesResolvingTests.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceModulesResolvingTests.java new file mode 100644 index 00000000000..0674dee51af --- /dev/null +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceModulesResolvingTests.java @@ -0,0 +1,56 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.workspace.validation; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.terasology.engine.core.module.ModuleManager; +import org.terasology.gestalt.naming.Name; + +import java.util.Set; +import java.util.stream.Stream; + +/** + * Example test for check modules dependency validations. + */ +public class WorkspaceModulesResolvingTests { + + public static Stream modulesAndModuleManager() { + System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); + ModuleManager temporary = new ModuleManager(""); + return temporary.getRegistry() + .getModuleIds() + .stream() + .map((name) -> Arguments.of(temporary, name)); + } + + public static Stream modulePairsAndModuleManager() { + System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); + ModuleManager temporary = new ModuleManager(""); + Set moduleIds = temporary.getRegistry() + .getModuleIds(); + return moduleIds + .stream() + .flatMap((name) -> moduleIds.stream().map((name2) -> Arguments.of(temporary, name, name2))); + } + + @DisplayName("Try to resolve and load module") + @ParameterizedTest(name = "{displayName} - {1}") + @MethodSource("modulesAndModuleManager") + void resolveAndLoadModule(ModuleManager moduleManager, Name moduleName) { + moduleManager.resolveAndLoadEnvironment(moduleName); + Assertions.assertNotNull(moduleManager.getEnvironment()); + } + + @DisplayName("Try to resolve and load pair modules") + @ParameterizedTest(name = "{displayName} - [{1}, {2}]") + @MethodSource("modulePairsAndModuleManager") + void resolveAndLoadPairModules(ModuleManager moduleManager, Name moduleName1, Name moduleName2) { + moduleManager.resolveAndLoadEnvironment(moduleName1, moduleName2); + Assertions.assertNotNull(moduleManager.getEnvironment()); + } +} From d81d35bf2a150218586987a852fb1f4a03be77ad Mon Sep 17 00:00:00 2001 From: darkweird Date: Mon, 15 Nov 2021 11:12:24 +0300 Subject: [PATCH 3/8] feature(PathFinding-Behaviour): add direct MTE dependency (for CI) --- facades/WorkspaceValidation/build.gradle | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/facades/WorkspaceValidation/build.gradle b/facades/WorkspaceValidation/build.gradle index e311564de44..428d00b05c3 100644 --- a/facades/WorkspaceValidation/build.gradle +++ b/facades/WorkspaceValidation/build.gradle @@ -24,16 +24,8 @@ dependencies { implementation "org.terasology:reflections:0.9.12-MB" implementation(platform(project(":modules"))) -// // For the "natives" configuration make it depend on the native files from LWJGL -// implementation platform("org.lwjgl:lwjgl-bom:$LwjglVersion") -// ["natives-linux", "natives-windows", "natives-macos"].forEach { -// implementation "org.lwjgl:lwjgl::$it" -// implementation "org.lwjgl:lwjgl-assimp::$it" -// implementation "org.lwjgl:lwjgl-glfw::$it" -// implementation "org.lwjgl:lwjgl-openal::$it" -// implementation "org.lwjgl:lwjgl-opengl::$it" -// implementation "org.lwjgl:lwjgl-stb::$it" -// } + + implementation("org.terasology.modules:ModuleTestingEnvironment:0.3.0+") implementation(group: 'com.google.guava', name: 'guava', version: '30.1-jre') From 907ea8fad408128290e708f7d1fbf04ad418534d Mon Sep 17 00:00:00 2001 From: darkweird Date: Mon, 15 Nov 2021 17:09:32 +0300 Subject: [PATCH 4/8] feature(PathFinding-Behaviour): add module wide behavior loading test (prefab and behavior) --- facades/WorkspaceValidation/build.gradle | 4 +- .../validation/WorkspaceBehaviorsTests.java | 98 ++++++++++++++++--- 2 files changed, 85 insertions(+), 17 deletions(-) diff --git a/facades/WorkspaceValidation/build.gradle b/facades/WorkspaceValidation/build.gradle index 428d00b05c3..989aa4af735 100644 --- a/facades/WorkspaceValidation/build.gradle +++ b/facades/WorkspaceValidation/build.gradle @@ -25,7 +25,9 @@ dependencies { implementation(platform(project(":modules"))) - implementation("org.terasology.modules:ModuleTestingEnvironment:0.3.0+") + implementation(project(":engine-tests")) + + implementation("org.terasology.modules:ModuleTestingEnvironment:0.3.3-SNAPSHOT") implementation(group: 'com.google.guava', name: 'guava', version: '30.1-jre') diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java index ae5665b6ac2..a839ac43923 100644 --- a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java @@ -3,39 +3,105 @@ package org.terasology.workspace.validation; -import org.junit.jupiter.params.provider.Arguments; +import com.google.common.collect.Streams; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DynamicContainer; +import org.junit.jupiter.api.DynamicNode; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; import org.terasology.engine.core.module.ModuleManager; -import org.terasology.gestalt.assets.AssetType; +import org.terasology.engine.entitySystem.prefab.Prefab; +import org.terasology.engine.logic.behavior.BehaviorComponent; +import org.terasology.engine.logic.behavior.asset.BehaviorTree; +import org.terasology.gestalt.assets.Asset; +import org.terasology.gestalt.assets.AssetData; +import org.terasology.gestalt.assets.ResourceUrn; import org.terasology.gestalt.assets.management.AssetManager; -import org.terasology.gestalt.assets.management.AssetTypeManager; -import org.terasology.gestalt.assets.module.ModuleAwareAssetTypeManagerImpl; -import org.terasology.gestalt.naming.Name; +import org.terasology.moduletestingenvironment.Engines; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.stream.Stream; public class WorkspaceBehaviorsTests { - public static Stream modulesAndModuleManager() { + @TestFactory + Stream behaviours() { System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); ModuleManager temporary = new ModuleManager(""); return temporary.getRegistry() .getModuleIds() .stream() - .map((name) -> Arguments.of(temporary, name)); + .map(moduleName -> { + EnginesAccessor engine = new EnginesAccessor(Set.of(moduleName.toString()), null); + AtomicReference assetManagerRef = new AtomicReference<>(); + return DynamicContainer.dynamicContainer(String.format("Module - %s", moduleName), Streams.concat( + Stream.of(engine).map((e) -> + DynamicTest.dynamicTest("setup", () -> { + e.setup(); + assetManagerRef.set(e.getHostContext().get(AssetManager.class)); + }) + ), + Stream.of(DynamicContainer.dynamicContainer("Assets tests", Stream.of( + asset( + assetManagerRef, + BehaviorTree.class, + (b) -> Assertions.assertNotNull(b.getData()) + ), + asset( + assetManagerRef, + Prefab.class, + prefab -> prefab.hasComponent(BehaviorComponent.class), + prefab -> Assertions.assertNotNull(prefab.getComponent(BehaviorComponent.class).tree) + + )))), + Stream.of(DynamicTest.dynamicTest("tearDown", engine::tearDown)))); + }); } - public static Stream modulePairsAndModuleManager() { - System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); - ModuleManager temporary = new ModuleManager(""); - Set moduleIds = temporary.getRegistry() - .getModuleIds(); - return moduleIds - .stream() - .flatMap((name) -> moduleIds.stream().map((name2) -> Arguments.of(temporary, name, name2))); + private > DynamicContainer asset(AtomicReference assetManager, + Class assetClazz, + Consumer validator) { + return asset(assetManager, assetClazz, (a) -> true, validator); + } - void behaviorTest() { + private > DynamicContainer asset(AtomicReference assetManager, + Class assetClazz, + Predicate filter, + Consumer validator) { + + return DynamicContainer.dynamicContainer(String.format("AssetType: %s", assetClazz.getSimpleName()), + DynamicTest.stream( + Stream.generate(() -> assetManager.get().getAvailableAssets(assetClazz).stream()) + .limit(1) + .flatMap(s -> s) + .filter(urn -> filter.test(assetManager.get().getAsset(urn, assetClazz).get())), + ResourceUrn::toString, + urn -> { + A asset = (A) assetManager.get().getAsset(urn, assetClazz).get(); + validator.accept(asset); + } + )); + + } + + public static class EnginesAccessor extends Engines { + + public EnginesAccessor(Set dependencies, String worldGeneratorUri) { + super(dependencies, worldGeneratorUri); + } + + @Override + protected void setup() { + super.setup(); + } + @Override + protected void tearDown() { + super.tearDown(); + } } } From 4c635b1d1d2e2d0286c44a7869049da546c74c37 Mon Sep 17 00:00:00 2001 From: darkweird Date: Mon, 15 Nov 2021 18:08:32 +0300 Subject: [PATCH 5/8] feature(PathFinding-Behaviour): add filter for behavior module-wide test. don't run modules without behavior asset,override or delta --- .../validation/WorkspaceBehaviorsTests.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java index a839ac43923..c7afba9d2cd 100644 --- a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java @@ -4,11 +4,13 @@ package org.terasology.workspace.validation; import com.google.common.collect.Streams; +import com.google.common.io.ByteStreams; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DynamicContainer; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; +import org.terasology.engine.core.TerasologyConstants; import org.terasology.engine.core.module.ModuleManager; import org.terasology.engine.entitySystem.prefab.Prefab; import org.terasology.engine.logic.behavior.BehaviorComponent; @@ -17,8 +19,12 @@ import org.terasology.gestalt.assets.AssetData; import org.terasology.gestalt.assets.ResourceUrn; import org.terasology.gestalt.assets.management.AssetManager; +import org.terasology.gestalt.module.Module; +import org.terasology.gestalt.module.resources.ModuleFileSource; import org.terasology.moduletestingenvironment.Engines; +import java.io.IOException; +import java.io.InputStream; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -34,6 +40,35 @@ Stream behaviours() { return temporary.getRegistry() .getModuleIds() .stream() + .filter(name -> { + Module module = temporary.getRegistry().getLatestModuleVersion(name); + ModuleFileSource resources = module.getResources(); + + boolean haveBehaviors = !resources.getFilesInPath(true, "assets/behaviors").isEmpty(); + boolean haveBehaviorOverride = + resources.getFilesInPath(false, "overrides") + .stream() + .anyMatch(fr -> fr.getPath().contains("behaviors")); + boolean haveBehaviorDelta = + resources.getFilesInPath(false, "deltas") + .stream() + .anyMatch(fr -> fr.getPath().contains("behaviors")); + + boolean havePrefab = resources.getFiles().stream() + .filter(fr -> fr.toString().contains("behaviours") && fr.toString().contains(".prefab")) + .anyMatch(fr -> { + try (InputStream inputStream = fr.open()) { + byte[] bytes = ByteStreams.toByteArray(inputStream); + String content = new String(bytes, TerasologyConstants.CHARSET); + return content.contains(BehaviorComponent.class.getSimpleName()); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + }); + + return haveBehaviors || haveBehaviorOverride || haveBehaviorDelta || havePrefab; + }) .map(moduleName -> { EnginesAccessor engine = new EnginesAccessor(Set.of(moduleName.toString()), null); AtomicReference assetManagerRef = new AtomicReference<>(); From fb1b63f04757a2a292f428f62b1a2b3006d64f7f Mon Sep 17 00:00:00 2001 From: darkweird Date: Tue, 16 Nov 2021 10:37:54 +0300 Subject: [PATCH 6/8] feature(Workspace-wide tests): refactor WorkspaceBehaviorsTests. decompose functions and provide comment strings. --- .../validation/WorkspaceBehaviorsTests.java | 150 +++++++++++------- 1 file changed, 96 insertions(+), 54 deletions(-) diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java index c7afba9d2cd..338d5c50876 100644 --- a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java @@ -3,7 +3,6 @@ package org.terasology.workspace.validation; -import com.google.common.collect.Streams; import com.google.common.io.ByteStreams; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DynamicContainer; @@ -19,15 +18,19 @@ import org.terasology.gestalt.assets.AssetData; import org.terasology.gestalt.assets.ResourceUrn; import org.terasology.gestalt.assets.management.AssetManager; +import org.terasology.gestalt.entitysystem.component.Component; import org.terasology.gestalt.module.Module; import org.terasology.gestalt.module.resources.ModuleFileSource; +import org.terasology.gestalt.naming.Name; import org.terasology.moduletestingenvironment.Engines; import java.io.IOException; import java.io.InputStream; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiPredicate; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; @@ -35,67 +38,104 @@ public class WorkspaceBehaviorsTests { @TestFactory Stream behaviours() { - System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); - ModuleManager temporary = new ModuleManager(""); - return temporary.getRegistry() + return template( + // Filter modules + haveAsset("behaviors").or(havePrefab(BehaviorComponent.class)), + // Create assetTests + assetManagerRef -> Stream.of( + asset( + assetManagerRef, + BehaviorTree.class, + (b) -> Assertions.assertNotNull(b.getData()) + ), + asset( + assetManagerRef, + Prefab.class, + prefab -> prefab.hasComponent(BehaviorComponent.class), + prefab -> Assertions.assertNotNull(prefab.getComponent(BehaviorComponent.class).tree) + + )) + ); + } + + + Stream template( + BiPredicate moduleFilter, + Function, + Stream> testsCreator) { + ModuleManager moduleManager = createModuleManager(); + return moduleManager.getRegistry() .getModuleIds() .stream() - .filter(name -> { - Module module = temporary.getRegistry().getLatestModuleVersion(name); - ModuleFileSource resources = module.getResources(); - - boolean haveBehaviors = !resources.getFilesInPath(true, "assets/behaviors").isEmpty(); - boolean haveBehaviorOverride = - resources.getFilesInPath(false, "overrides") - .stream() - .anyMatch(fr -> fr.getPath().contains("behaviors")); - boolean haveBehaviorDelta = - resources.getFilesInPath(false, "deltas") - .stream() - .anyMatch(fr -> fr.getPath().contains("behaviors")); - - boolean havePrefab = resources.getFiles().stream() - .filter(fr -> fr.toString().contains("behaviours") && fr.toString().contains(".prefab")) - .anyMatch(fr -> { - try (InputStream inputStream = fr.open()) { - byte[] bytes = ByteStreams.toByteArray(inputStream); - String content = new String(bytes, TerasologyConstants.CHARSET); - return content.contains(BehaviorComponent.class.getSimpleName()); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - }); - - return haveBehaviors || haveBehaviorOverride || haveBehaviorDelta || havePrefab; - }) + // use filter over modules + .filter(name -> moduleFilter.test(moduleManager, name)) + // create tests .map(moduleName -> { + // Create engine EnginesAccessor engine = new EnginesAccessor(Set.of(moduleName.toString()), null); + // Provide `Lazy` reference for asset tests AtomicReference assetManagerRef = new AtomicReference<>(); - return DynamicContainer.dynamicContainer(String.format("Module - %s", moduleName), Streams.concat( - Stream.of(engine).map((e) -> + return DynamicContainer.dynamicContainer(String.format("Module - %s", moduleName), + Stream.of( + // engine test DynamicTest.dynamicTest("setup", () -> { - e.setup(); - assetManagerRef.set(e.getHostContext().get(AssetManager.class)); - }) - ), - Stream.of(DynamicContainer.dynamicContainer("Assets tests", Stream.of( - asset( - assetManagerRef, - BehaviorTree.class, - (b) -> Assertions.assertNotNull(b.getData()) - ), - asset( - assetManagerRef, - Prefab.class, - prefab -> prefab.hasComponent(BehaviorComponent.class), - prefab -> Assertions.assertNotNull(prefab.getComponent(BehaviorComponent.class).tree) - - )))), - Stream.of(DynamicTest.dynamicTest("tearDown", engine::tearDown)))); + engine.setup(); + assetManagerRef.set(engine.getHostContext().get(AssetManager.class)); + }), + // Container with asset tests + DynamicContainer.dynamicContainer("Assets tests", testsCreator.apply(assetManagerRef)), + // engine teardown test + DynamicTest.dynamicTest("tearDown", engine::tearDown))); }); } + private ModuleManager createModuleManager() { + System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); + return new ModuleManager(""); + } + + private BiPredicate haveAsset(String assetName) { + return (moduleManager, name) -> { + Module module = moduleManager.getRegistry().getLatestModuleVersion(name); + ModuleFileSource resources = module.getResources(); + + boolean haveAsset = !resources.getFilesInPath(true, "assets/" + assetName).isEmpty(); + + boolean haveAssetOverride = + resources.getFilesInPath(false, "overrides") + .stream() + .anyMatch(fr -> fr.getPath().contains(assetName)); + boolean haveAssetDelta = + resources.getFilesInPath(false, "deltas") + .stream() + .anyMatch(fr -> fr.getPath().contains(assetName)); + + return haveAsset || haveAssetOverride || haveAssetDelta; + }; + } + + + private > BiPredicate havePrefab(Class componentClass) { + return (moduleManager, name) -> { + Module module = moduleManager.getRegistry().getLatestModuleVersion(name); + ModuleFileSource resources = module.getResources(); + + return resources.getFiles().stream() + .filter(fr -> fr.toString().contains("prefabs") && fr.toString().contains(".prefab")) + .anyMatch(fr -> { + try (InputStream inputStream = fr.open()) { + byte[] bytes = ByteStreams.toByteArray(inputStream); + String content = new String(bytes, TerasologyConstants.CHARSET); + String componentName = componentClass.getSimpleName(); + return content.contains(componentName); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + }); + }; + } + private > DynamicContainer asset(AtomicReference assetManager, Class assetClazz, Consumer validator) { @@ -110,19 +150,21 @@ private > DynamicContainer asset(AtomicR return DynamicContainer.dynamicContainer(String.format("AssetType: %s", assetClazz.getSimpleName()), DynamicTest.stream( + // Special generator for 1 value for `lazy` getting. Stream.generate(() -> assetManager.get().getAvailableAssets(assetClazz).stream()) .limit(1) .flatMap(s -> s) .filter(urn -> filter.test(assetManager.get().getAsset(urn, assetClazz).get())), ResourceUrn::toString, urn -> { - A asset = (A) assetManager.get().getAsset(urn, assetClazz).get(); + A asset = assetManager.get().getAsset(urn, assetClazz).get(); validator.accept(asset); } )); } + // Just grant access to protected methods. public static class EnginesAccessor extends Engines { public EnginesAccessor(Set dependencies, String worldGeneratorUri) { From 55eca214a98e37240700aa2220db84bb329a0754 Mon Sep 17 00:00:00 2001 From: darkweird Date: Tue, 16 Nov 2021 11:51:07 +0300 Subject: [PATCH 7/8] feature(Workspace-wide tests): extract `AssetTesting` functions. `AssetTesting#template` can be reused for any tests. --- .../workspace/validation/AssetTesting.java | 166 ++++++++++++++++++ .../validation/WorkspaceBehaviorsTests.java | 125 +------------ 2 files changed, 167 insertions(+), 124 deletions(-) create mode 100644 facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/AssetTesting.java diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/AssetTesting.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/AssetTesting.java new file mode 100644 index 00000000000..199b6457441 --- /dev/null +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/AssetTesting.java @@ -0,0 +1,166 @@ +// Copyright 2021 The Terasology Foundation +// SPDX-License-Identifier: Apache-2.0 + +package org.terasology.workspace.validation; + +import com.google.common.io.ByteStreams; +import org.junit.jupiter.api.DynamicContainer; +import org.junit.jupiter.api.DynamicNode; +import org.junit.jupiter.api.DynamicTest; +import org.terasology.engine.core.TerasologyConstants; +import org.terasology.engine.core.module.ModuleManager; +import org.terasology.gestalt.assets.Asset; +import org.terasology.gestalt.assets.AssetData; +import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.gestalt.assets.management.AssetManager; +import org.terasology.gestalt.entitysystem.component.Component; +import org.terasology.gestalt.module.Module; +import org.terasology.gestalt.module.resources.ModuleFileSource; +import org.terasology.gestalt.naming.Name; +import org.terasology.moduletestingenvironment.Engines; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Stream; + +/** + * Set of functions for testing assets. + */ +public class AssetTesting { + /** + * Template for assets tests. + *

+ * Provide engine setup, engine tearup and {@code testsCretor}'s content as tests. + * + * @param moduleFilter - filter. which modules should be runs with {@code testsCreator}'s tests. + * @param testsCreator - function which provides asset tests. + * @return Stream of DynamicNodes. requred for junit-jupiter's dynamic tests. + */ + public Stream template( + BiPredicate moduleFilter, + Function, + Stream> testsCreator) { + ModuleManager moduleManager = createModuleManager(); + return moduleManager.getRegistry() + .getModuleIds() + .stream() + // use filter over modules + .filter(name -> moduleFilter.test(moduleManager, name)) + // create tests + .map(moduleName -> { + // Create engine + EnginesAccessor engine = new EnginesAccessor(Set.of(moduleName.toString()), null); + // Provide `Lazy` reference for asset tests + AtomicReference assetManagerRef = new AtomicReference<>(); + return DynamicContainer.dynamicContainer(String.format("Module - %s", moduleName), + Stream.of( + // engine test + DynamicTest.dynamicTest("setup", () -> { + engine.setup(); + assetManagerRef.set(engine.getHostContext().get(AssetManager.class)); + }), + // Container with asset tests + DynamicContainer.dynamicContainer("Assets tests", testsCreator.apply(assetManagerRef)), + // engine teardown test + DynamicTest.dynamicTest("tearDown", engine::tearDown))); + }); + } + + public ModuleManager createModuleManager() { + System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); + return new ModuleManager(""); + } + + public BiPredicate haveAsset(String assetName) { + return (moduleManager, name) -> { + Module module = moduleManager.getRegistry().getLatestModuleVersion(name); + ModuleFileSource resources = module.getResources(); + + boolean haveAsset = !resources.getFilesInPath(true, "assets/" + assetName).isEmpty(); + + boolean haveAssetOverride = + resources.getFilesInPath(false, "overrides") + .stream() + .anyMatch(fr -> fr.getPath().contains(assetName)); + boolean haveAssetDelta = + resources.getFilesInPath(false, "deltas") + .stream() + .anyMatch(fr -> fr.getPath().contains(assetName)); + + return haveAsset || haveAssetOverride || haveAssetDelta; + }; + } + + public > BiPredicate havePrefab(Class componentClass) { + return (moduleManager, name) -> { + Module module = moduleManager.getRegistry().getLatestModuleVersion(name); + ModuleFileSource resources = module.getResources(); + + return resources.getFiles().stream() + .filter(fr -> fr.toString().contains("prefabs") && fr.toString().contains(".prefab")) + .anyMatch(fr -> { + try (InputStream inputStream = fr.open()) { + byte[] bytes = ByteStreams.toByteArray(inputStream); + String content = new String(bytes, TerasologyConstants.CHARSET); + String componentName = componentClass.getSimpleName(); + return content.contains(componentName); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + }); + }; + } + + public > DynamicContainer asset(AtomicReference assetManager, + Class assetClazz, + Consumer validator) { + return asset(assetManager, assetClazz, (a) -> true, validator); + + } + + public > DynamicContainer asset(AtomicReference assetManager, + Class assetClazz, + Predicate filter, + Consumer validator) { + + return DynamicContainer.dynamicContainer(String.format("AssetType: %s", assetClazz.getSimpleName()), + DynamicTest.stream( + // Special generator for 1 value for `lazy` getting. + Stream.generate(() -> assetManager.get().getAvailableAssets(assetClazz).stream()) + .limit(1) + .flatMap(s -> s) + .filter(urn -> filter.test(assetManager.get().getAsset(urn, assetClazz).get())), + ResourceUrn::toString, + urn -> { + A asset = assetManager.get().getAsset(urn, assetClazz).get(); + validator.accept(asset); + } + )); + + } + + // Just grant access to protected methods. + public static class EnginesAccessor extends Engines { + + public EnginesAccessor(Set dependencies, String worldGeneratorUri) { + super(dependencies, worldGeneratorUri); + } + + @Override + protected void setup() { + super.setup(); + } + + @Override + protected void tearDown() { + super.tearDown(); + } + } +} diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java index 338d5c50876..ff9c57bbc0e 100644 --- a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java @@ -34,7 +34,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; -public class WorkspaceBehaviorsTests { +public class WorkspaceBehaviorsTests extends AssetTesting { @TestFactory Stream behaviours() { @@ -58,127 +58,4 @@ Stream behaviours() { ); } - - Stream template( - BiPredicate moduleFilter, - Function, - Stream> testsCreator) { - ModuleManager moduleManager = createModuleManager(); - return moduleManager.getRegistry() - .getModuleIds() - .stream() - // use filter over modules - .filter(name -> moduleFilter.test(moduleManager, name)) - // create tests - .map(moduleName -> { - // Create engine - EnginesAccessor engine = new EnginesAccessor(Set.of(moduleName.toString()), null); - // Provide `Lazy` reference for asset tests - AtomicReference assetManagerRef = new AtomicReference<>(); - return DynamicContainer.dynamicContainer(String.format("Module - %s", moduleName), - Stream.of( - // engine test - DynamicTest.dynamicTest("setup", () -> { - engine.setup(); - assetManagerRef.set(engine.getHostContext().get(AssetManager.class)); - }), - // Container with asset tests - DynamicContainer.dynamicContainer("Assets tests", testsCreator.apply(assetManagerRef)), - // engine teardown test - DynamicTest.dynamicTest("tearDown", engine::tearDown))); - }); - } - - private ModuleManager createModuleManager() { - System.setProperty(ModuleManager.LOAD_CLASSPATH_MODULES_PROPERTY, "true"); - return new ModuleManager(""); - } - - private BiPredicate haveAsset(String assetName) { - return (moduleManager, name) -> { - Module module = moduleManager.getRegistry().getLatestModuleVersion(name); - ModuleFileSource resources = module.getResources(); - - boolean haveAsset = !resources.getFilesInPath(true, "assets/" + assetName).isEmpty(); - - boolean haveAssetOverride = - resources.getFilesInPath(false, "overrides") - .stream() - .anyMatch(fr -> fr.getPath().contains(assetName)); - boolean haveAssetDelta = - resources.getFilesInPath(false, "deltas") - .stream() - .anyMatch(fr -> fr.getPath().contains(assetName)); - - return haveAsset || haveAssetOverride || haveAssetDelta; - }; - } - - - private > BiPredicate havePrefab(Class componentClass) { - return (moduleManager, name) -> { - Module module = moduleManager.getRegistry().getLatestModuleVersion(name); - ModuleFileSource resources = module.getResources(); - - return resources.getFiles().stream() - .filter(fr -> fr.toString().contains("prefabs") && fr.toString().contains(".prefab")) - .anyMatch(fr -> { - try (InputStream inputStream = fr.open()) { - byte[] bytes = ByteStreams.toByteArray(inputStream); - String content = new String(bytes, TerasologyConstants.CHARSET); - String componentName = componentClass.getSimpleName(); - return content.contains(componentName); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - }); - }; - } - - private > DynamicContainer asset(AtomicReference assetManager, - Class assetClazz, - Consumer validator) { - return asset(assetManager, assetClazz, (a) -> true, validator); - - } - - private > DynamicContainer asset(AtomicReference assetManager, - Class assetClazz, - Predicate filter, - Consumer validator) { - - return DynamicContainer.dynamicContainer(String.format("AssetType: %s", assetClazz.getSimpleName()), - DynamicTest.stream( - // Special generator for 1 value for `lazy` getting. - Stream.generate(() -> assetManager.get().getAvailableAssets(assetClazz).stream()) - .limit(1) - .flatMap(s -> s) - .filter(urn -> filter.test(assetManager.get().getAsset(urn, assetClazz).get())), - ResourceUrn::toString, - urn -> { - A asset = assetManager.get().getAsset(urn, assetClazz).get(); - validator.accept(asset); - } - )); - - } - - // Just grant access to protected methods. - public static class EnginesAccessor extends Engines { - - public EnginesAccessor(Set dependencies, String worldGeneratorUri) { - super(dependencies, worldGeneratorUri); - } - - @Override - protected void setup() { - super.setup(); - } - - @Override - protected void tearDown() { - super.tearDown(); - } - } } From eaee6bafc914665b80e54db227c94e5b7ff164dd Mon Sep 17 00:00:00 2001 From: darkweird Date: Tue, 16 Nov 2021 11:58:30 +0300 Subject: [PATCH 8/8] chore(Workspace-wide tests): format code --- .../validation/WorkspaceBehaviorsTests.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java index ff9c57bbc0e..40c8fb750cf 100644 --- a/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java +++ b/facades/WorkspaceValidation/src/test/java/org/terasology/workspace/validation/WorkspaceBehaviorsTests.java @@ -3,35 +3,13 @@ package org.terasology.workspace.validation; -import com.google.common.io.ByteStreams; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DynamicContainer; import org.junit.jupiter.api.DynamicNode; -import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; -import org.terasology.engine.core.TerasologyConstants; -import org.terasology.engine.core.module.ModuleManager; import org.terasology.engine.entitySystem.prefab.Prefab; import org.terasology.engine.logic.behavior.BehaviorComponent; import org.terasology.engine.logic.behavior.asset.BehaviorTree; -import org.terasology.gestalt.assets.Asset; -import org.terasology.gestalt.assets.AssetData; -import org.terasology.gestalt.assets.ResourceUrn; -import org.terasology.gestalt.assets.management.AssetManager; -import org.terasology.gestalt.entitysystem.component.Component; -import org.terasology.gestalt.module.Module; -import org.terasology.gestalt.module.resources.ModuleFileSource; -import org.terasology.gestalt.naming.Name; -import org.terasology.moduletestingenvironment.Engines; -import java.io.IOException; -import java.io.InputStream; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiPredicate; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; import java.util.stream.Stream; public class WorkspaceBehaviorsTests extends AssetTesting {