forked from Clones/Controlify
test framework
This commit is contained in:
@ -0,0 +1,45 @@
|
||||
package dev.isxander.controlify.test;
|
||||
|
||||
public class Assertions {
|
||||
public static void assertEquals(Object expected, Object actual) {
|
||||
assertTrue(expected.equals(actual), "Expected " + expected + " but got " + actual);
|
||||
}
|
||||
|
||||
public static void assertEquals(Object expected, Object actual, String message) {
|
||||
assertTrue(expected.equals(actual), message);
|
||||
}
|
||||
|
||||
public static void assertNotNull(Object object) {
|
||||
assertTrue(object != null, "Expected object to not be null");
|
||||
}
|
||||
|
||||
public static void assertNotNull(Object object, String message) {
|
||||
assertTrue(object != null, message);
|
||||
}
|
||||
|
||||
public static void assertNull(Object object) {
|
||||
assertTrue(object == null, "Expected object to be null");
|
||||
}
|
||||
|
||||
public static void assertNull(Object object, String message) {
|
||||
assertTrue(object == null, message);
|
||||
}
|
||||
|
||||
public static void assertTrue(boolean condition) {
|
||||
assertTrue(condition, "Condition not met");
|
||||
}
|
||||
|
||||
public static void assertTrue(boolean condition, String message) {
|
||||
if (!condition) {
|
||||
throw new AssertionError(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertFalse(boolean condition) {
|
||||
assertTrue(!condition, "Condition not met");
|
||||
}
|
||||
|
||||
public static void assertFalse(boolean condition, String message) {
|
||||
assertTrue(!condition, message);
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
package dev.isxander.controlify.test;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import dev.isxander.controlify.bindings.ControllerBindings;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.controller.ControllerConfig;
|
||||
import dev.isxander.controlify.controller.ControllerState;
|
||||
import dev.isxander.controlify.controller.ControllerType;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ClientTestHelper {
|
||||
public static void waitForLoadingComplete() {
|
||||
waitFor("Loading to complete", client -> client.getOverlay() == null, Duration.ofMinutes(5));
|
||||
}
|
||||
|
||||
public static void waitFor(String what, Predicate<Minecraft> condition, Duration timeout) {
|
||||
final LocalDateTime end = LocalDateTime.now().plus(timeout);
|
||||
|
||||
while (true) {
|
||||
boolean result = submitAndWait(condition::test);
|
||||
|
||||
if (result) break;
|
||||
|
||||
if (LocalDateTime.now().isAfter(end)) {
|
||||
throw new RuntimeException("Timed out waiting for " + what + " to complete. (timeout: " + timeout + ")");
|
||||
}
|
||||
|
||||
waitFor(Duration.ofSeconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
public static void waitFor(Duration duration) {
|
||||
try {
|
||||
Thread.sleep(duration.toMillis());
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> CompletableFuture<T> submit(Function<Minecraft, T> function) {
|
||||
return Minecraft.getInstance().submit(() -> function.apply(Minecraft.getInstance()));
|
||||
}
|
||||
|
||||
public static <T> T submitAndWait(Function<Minecraft, T> function) {
|
||||
return submit(function).join();
|
||||
}
|
||||
|
||||
public static Controller<?, ?> createFakeController() {
|
||||
return new Controller<>() {
|
||||
private final ControllerBindings<ControllerState> bindings = new ControllerBindings<>(this);
|
||||
private final ControllerConfig config = new ControllerConfig() {
|
||||
@Override
|
||||
public void setDeadzone(int axis, float deadzone) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDeadzone(int axis) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String uid() {
|
||||
return "FAKE";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String guid() {
|
||||
return "FAKE";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControllerBindings<ControllerState> bindings() {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControllerConfig config() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControllerConfig defaultConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConfig() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(Gson gson, JsonElement json) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControllerType type() {
|
||||
return ControllerType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "FAKE CONTROLLER";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControllerState state() {
|
||||
return ControllerState.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControllerState prevState() {
|
||||
return ControllerState.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState() {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package dev.isxander.controlify.test;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import static dev.isxander.controlify.test.ClientTestHelper.*;
|
||||
|
||||
public class ControlifyAutoTestClient implements ClientModInitializer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Controlify Auto Test");
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
var thread = new Thread(() -> {
|
||||
try {
|
||||
runTests(ControlifyTests.class);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
});
|
||||
thread.setName("Controlify Auto Test Thread");
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void runTests(Class<?> testClass) throws Exception {
|
||||
List<Test> preLoadTests = Lists.newArrayList();
|
||||
List<Test> postLoadTests = Lists.newArrayList();
|
||||
|
||||
Object testObject = testClass.getConstructor().newInstance();
|
||||
|
||||
Method[] methods = testClass.getDeclaredMethods();
|
||||
for (var method : methods) {
|
||||
method.setAccessible(true);
|
||||
|
||||
Test.PreLoad preLoad = method.getAnnotation(Test.PreLoad.class);
|
||||
if (preLoad != null) {
|
||||
if (method.getParameterCount() > 0)
|
||||
throw new RuntimeException("PreLoad test method " + method.getName() + " has parameters!");
|
||||
|
||||
preLoadTests.add(new Test(() -> {
|
||||
try {
|
||||
method.invoke(testObject);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, preLoad.value()));
|
||||
}
|
||||
|
||||
Test.PostLoad postLoad = method.getAnnotation(Test.PostLoad.class);
|
||||
if (postLoad != null) {
|
||||
if (method.getParameterCount() > 0)
|
||||
throw new RuntimeException("PostLoad test method " + method.getName() + " has parameters!");
|
||||
|
||||
postLoadTests.add(new Test(() -> {
|
||||
try {
|
||||
method.invoke(testObject);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, postLoad.value()));
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = true;
|
||||
for (var test : preLoadTests) {
|
||||
success &= wrapTest(test);
|
||||
}
|
||||
|
||||
waitForLoadingComplete();
|
||||
|
||||
for (var test : postLoadTests) {
|
||||
success &= wrapTest(test);
|
||||
}
|
||||
|
||||
System.exit(success ? 0 : 1);
|
||||
}
|
||||
|
||||
private boolean wrapTest(Test test) {
|
||||
LOGGER.info("\u001b[36mRunning test " + test.name() + "...");
|
||||
try {
|
||||
test.method().run();
|
||||
LOGGER.info("\u001b[32mPassed test " + test.name() + "!");
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error("\u001b[31mFailed test " + test.name() + "!", t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package dev.isxander.controlify.test;
|
||||
|
||||
import dev.isxander.controlify.InputMode;
|
||||
import dev.isxander.controlify.api.ControlifyApi;
|
||||
import dev.isxander.controlify.api.bind.ControlifyBindingsApi;
|
||||
import dev.isxander.controlify.api.event.ControlifyEvents;
|
||||
import dev.isxander.controlify.bindings.BindingSupplier;
|
||||
import dev.isxander.controlify.bindings.GamepadBinds;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static dev.isxander.controlify.test.Assertions.*;
|
||||
import static dev.isxander.controlify.test.ClientTestHelper.*;
|
||||
|
||||
public class ControlifyTests {
|
||||
BindingSupplier binding = null;
|
||||
|
||||
@Test.PreLoad("Binding registry test")
|
||||
void bindingRegistryTest() {
|
||||
var registry = ControlifyBindingsApi.get();
|
||||
assertNotNull(registry, "Binding registry is null");
|
||||
binding = registry.registerBind(GamepadBinds.A_BUTTON, new ResourceLocation("controlify", "test_bind"));
|
||||
assertNotNull(binding, "Bind registry failed - BindingSupplier is null");
|
||||
}
|
||||
|
||||
@Test.PostLoad("BindingSupplier getter test")
|
||||
void bindingSupplierGetterTest() {
|
||||
var controller = createFakeController();
|
||||
assertNotNull(binding.get(controller), "Bind registry failed - Bind for fake controller is null");
|
||||
}
|
||||
|
||||
@Test.PostLoad("Input mode changed event test")
|
||||
void checkInputModeChangedEvent() {
|
||||
var api = ControlifyApi.get();
|
||||
|
||||
AtomicBoolean called = new AtomicBoolean(false);
|
||||
|
||||
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> called.set(true));
|
||||
api.setInputMode(InputMode.CONTROLLER);
|
||||
api.setInputMode(InputMode.KEYBOARD_MOUSE);
|
||||
|
||||
assertTrue(called.get(), "Input mode changed event was not called");
|
||||
}
|
||||
}
|
20
src/testmod/java/dev/isxander/controlify/test/Test.java
Normal file
20
src/testmod/java/dev/isxander/controlify/test/Test.java
Normal file
@ -0,0 +1,20 @@
|
||||
package dev.isxander.controlify.test;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
public record Test(Runnable method, String name) {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface PreLoad {
|
||||
String value();
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface PostLoad {
|
||||
String value();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user