Minestom/testing/src/main/java/net/minestom/testing/EnvImpl.java

106 lines
3.3 KiB
Java

package net.minestom.testing;
import net.minestom.server.ServerProcess;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventFilter;
import net.minestom.server.event.EventListener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
final class EnvImpl implements Env {
private final ServerProcess process;
private final List<FlexibleListenerImpl<?>> listeners = new CopyOnWriteArrayList<>();
public EnvImpl(ServerProcess process) {
this.process = process;
}
@Override
public @NotNull ServerProcess process() {
return process;
}
@Override
public @NotNull TestConnection createConnection() {
return new TestConnectionImpl(this);
}
@Override
public @NotNull <E extends Event, H> Collector<E> trackEvent(@NotNull Class<E> eventType, @NotNull EventFilter<? super E, H> filter, @NotNull H actor) {
var tracker = new EventCollector<E>(actor);
this.process.eventHandler().map(actor, filter).addListener(eventType, tracker.events::add);
return tracker;
}
@Override
public @NotNull <E extends Event> FlexibleListener<E> listen(@NotNull Class<E> eventType) {
var handler = process.eventHandler();
var flexible = new FlexibleListenerImpl<>(eventType);
var listener = EventListener.of(eventType, e -> flexible.handler.accept(e));
handler.addListener(listener);
this.listeners.add(flexible);
return flexible;
}
void cleanup() {
this.listeners.forEach(FlexibleListenerImpl::check);
}
final class EventCollector<E extends Event> implements Collector<E> {
private final Object handler;
private final List<E> events = new CopyOnWriteArrayList<>();
public EventCollector(Object handler) {
this.handler = handler;
}
@Override
public @NotNull List<E> collect() {
process.eventHandler().unmap(handler);
return List.copyOf(events);
}
}
static final class FlexibleListenerImpl<E extends Event> implements FlexibleListener<E> {
private final Class<E> eventType;
private Consumer<E> handler = e -> {
};
private boolean initialized;
private boolean called;
FlexibleListenerImpl(Class<E> eventType) {
this.eventType = eventType;
}
@Override
public void followup(@NotNull Consumer<E> handler) {
updateHandler(handler);
}
@Override
public void failFollowup() {
updateHandler(e -> fail("Event " + e.getClass().getSimpleName() + " was not expected"));
}
void updateHandler(@NotNull Consumer<E> handler) {
check();
this.initialized = true;
this.called = false;
this.handler = e -> {
handler.accept(e);
this.called = true;
};
}
void check() {
assertTrue(!initialized || called, "Last listener has not been called: " + eventType.getSimpleName());
}
}
}