Skip to content

Commit

Permalink
multithreading
Browse files Browse the repository at this point in the history
  • Loading branch information
J3fftw1 committed Nov 20, 2023
1 parent 19eea2f commit a55e3a1
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 52 deletions.
13 changes: 13 additions & 0 deletions src/main/java/io/github/slimefun/e2etester/E2ETester.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,26 @@

public class E2ETester extends JavaPlugin {

private static E2ETester instance;

@Override
public void onEnable() {
instance = this;

final TestFramework framework = TestFramework.newTestRun();

// Wait a second for any startup stuff to be ran
Bukkit.getScheduler().runTaskLater(this, () -> {
framework.runTests("io.github.slimefun.e2etester.tests");
}, 20);
}

@Override
public void onDisable() {
instance = null;
}

public static E2ETester getInstance() {
return instance;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package io.github.slimefun.e2etester.framework;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import javax.annotation.Nonnull;

import io.github.slimefun.e2etester.E2ETester;
import org.bukkit.Bukkit;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
Expand All @@ -24,6 +29,7 @@
public class TestFramework {

private final Map<String, ArrayList<Consumer<Void>>> eventListeners = new HashMap<>();
private final ExecutorService service = Executors.newSingleThreadExecutor();

private int testsRan;
private int testsPassed;
Expand All @@ -41,63 +47,76 @@ public void runTests(@Nonnull String packageName) {
// TODO: Remove
new Startup();

// Reflection go through all classes
Reflections reflections = new Reflections(ConfigurationBuilder
.build()
.addScanners(Scanners.values())
.forPackage(packageName, getClass().getClassLoader())
);

logMessage("Running tests...");
logMessage("");

final Set<Method> testMethods = reflections.get(Scanners.MethodsAnnotated.with(E2ETest.class).as(Method.class));
final Map<Class<?>, List<Method>> tests = orderTests(testMethods);
for (Map.Entry<Class<?>, List<Method>> entry : tests.entrySet()) {
logMessage("%s:", entry.getKey().getName());

for (Method method : entry.getValue()) {
String description = method.getAnnotation(E2ETest.class).description();

// Invoke
try {
testsRan++;

method.setAccessible(true);
Object instance = method.getDeclaringClass().getDeclaredConstructor().newInstance();
method.invoke(instance);

testsPassed++;
logMessage(" ✔ %s", description);
} catch(TestFailException e) {
testsFailed++;
logMessage(" x %s", description);
e.printStackTrace();
} catch(Exception e) {
testsFailed++;
logMessage(" x %s", description);
e.printStackTrace();
service.submit(() -> {
// Reflection go through all classes
Reflections reflections = new Reflections(ConfigurationBuilder
.build()
.addScanners(Scanners.values())
.forPackage(packageName, getClass().getClassLoader())
);

logMessage("Running tests...");
logMessage("");

final Set<Method> testMethods = reflections.get(Scanners.MethodsAnnotated.with(E2ETest.class).as(Method.class));
final Map<Class<?>, List<Method>> tests = orderTests(testMethods);
for (Map.Entry<Class<?>, List<Method>> entry : tests.entrySet()) {
logMessage("%s:", entry.getKey().getName());

for (Method method : entry.getValue()) {
E2ETest annotation = method.getAnnotation(E2ETest.class);
String description = annotation.description();
boolean threadSafe = annotation.threadSafe();
// Invoke
try {
testsRan++;

method.setAccessible(true);
Object instance = method.getDeclaringClass().getDeclaredConstructor().newInstance();
if (threadSafe) {
method.invoke(instance);
} else {
Bukkit.getScheduler().runTask(E2ETester.getInstance(), () -> {
try {
method.invoke(instance);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
});
}

testsPassed++;
logMessage(" ✔ %s", description);
} catch(TestFailException e) {
testsFailed++;
logMessage(" x %s", description);
e.printStackTrace();
} catch(Exception e) {
testsFailed++;
logMessage(" x %s", description);
e.printStackTrace();
}
}
}
}

logMessage("");
logMessage("Test results:");
logMessage(" Tests ran: %d", this.testsRan);
logMessage(" Tests passed: %d", this.testsPassed);
logMessage(" Tests failed: %d", this.testsFailed);
logMessage(" Tests skipped: %d", this.testsSkipped);

if (this.testsFailed > 0) {
logMessage("Test failure, exiting with code 1");
System.exit(1);
} else {
Bukkit.shutdown();
}
logMessage("");
logMessage("Test results:");
logMessage(" Tests ran: %d", this.testsRan);
logMessage(" Tests passed: %d", this.testsPassed);
logMessage(" Tests failed: %d", this.testsFailed);
logMessage(" Tests skipped: %d", this.testsSkipped);

if (this.testsFailed > 0) {
logMessage("Test failure, exiting with code 1");
System.exit(1);
} else {
Bukkit.getScheduler().runTask(E2ETester.getInstance(), Bukkit::shutdown);
}
});
}

public void on(@Nonnull String event, Consumer<Void> consumer) {
eventListeners.putIfAbsent(event, new ArrayList<Consumer<Void>>());
eventListeners.putIfAbsent(event, new ArrayList<>());

ArrayList<Consumer<Void>> value = eventListeners.get(event);
if (value != null) {
Expand Down Expand Up @@ -146,7 +165,7 @@ private Map<Class<?>, List<Method>> orderTests(Set<Method> methods) {
return tests.entrySet().stream()
.sorted((entry1, entry2) -> entry1.getKey().getName().compareTo(entry2.getKey().getName()))
.collect(Collectors.toMap(
entry -> entry.getKey(),
Map.Entry::getKey,
value -> value.getValue().stream()
.sorted((method1, method2) -> method1.getName().compareTo(method2.getName()))
.toList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
public @interface E2ETest {

String description();
boolean threadSafe() default false;
}

0 comments on commit a55e3a1

Please sign in to comment.