package com.jcwhatever.nucleus.utils.observer.event; import static org.junit.Assert.assertEquals; import com.jcwhatever.nucleus.mixins.ICancellable; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.annotation.Nullable; public class EventAgentTest { @Test public void basicTest() { final List<String> callResults = new ArrayList<>(10); EventAgent agent = new EventAgent(); EventSubscriber<String> subscriber = getSubscriber(callResults); assertEquals(0, agent.getSubscribers().size()); agent.addSubscriber(subscriber); // ensure subscriber is added to agent assertEquals(1, agent.getSubscribers().size()); // ensure agent added itself to subscriber assertEquals(1, subscriber.getAgents().size()); // test event call agent.call(this, "testEvent"); // ensure the event was called on the subscriber assertEquals(1, callResults.size()); callResults.clear(); // test unregister agent.removeSubscriber(subscriber); // ensure subscriber is removed from agent assertEquals(0, agent.getSubscribers().size()); // ensure the agent removed itself from the subscriber assertEquals(0, subscriber.getAgents().size()); // test event call agent.call(this, "testEvent"); // ensure the event was NOT called on the subscriber assertEquals(0, callResults.size()); } @Test public void testEventOrder() { final List<String> callResults = new ArrayList<>(10); EventAgent agent = new EventAgent() {}; EventSubscriber<String> first = getSubscriber(callResults) .setPriority(EventSubscriberPriority.FIRST); EventSubscriber<String> high = getSubscriber(callResults) .setPriority(EventSubscriberPriority.HIGH); EventSubscriber<String> normal = getSubscriber(callResults) .setPriority(EventSubscriberPriority.NORMAL); EventSubscriber<String> low = getSubscriber(callResults) .setPriority(EventSubscriberPriority.LOW); EventSubscriber<String> last = getSubscriber(callResults) .setPriority(EventSubscriberPriority.LAST); EventSubscriber<String> watcher = getSubscriber(callResults) .setPriority(EventSubscriberPriority.WATCHER); // add events out of order to ensure they are sorted to the correct order agent.addSubscriber(normal); agent.addSubscriber(high); agent.addSubscriber(low); agent.addSubscriber(watcher); agent.addSubscriber(last); agent.addSubscriber(first); agent.call(this, "testEvent"); assertEquals(6, callResults.size()); assertEquals("FIRST", callResults.get(0)); assertEquals("HIGH", callResults.get(1)); assertEquals("NORMAL", callResults.get(2)); assertEquals("LOW", callResults.get(3)); assertEquals("LAST", callResults.get(4)); assertEquals("WATCHER", callResults.get(5)); } @Test public void testEventCancel() { final List<String> callResults = new ArrayList<>(10); EventAgent agent = new EventAgent() {}; EventSubscriber<CancelEvent> first = getCancellingSubscriber(callResults) .setPriority(EventSubscriberPriority.FIRST); EventSubscriber<CancelEvent> last = getSubscriber(callResults) .setPriority(EventSubscriberPriority.HIGH); EventSubscriber<CancelEvent> watcher = getSubscriber(callResults) .setPriority(EventSubscriberPriority.WATCHER); agent.addSubscriber(first); agent.addSubscriber(last); agent.addSubscriber(watcher); CancelEvent event = new CancelEvent(); assertEquals(false, event.isCancelled()); agent.call(this, event); // first should have cancelled event, high is not run, watcher is always run. assertEquals(2, callResults.size()); // reset callResults.clear(); event.setCancelled(false); assertEquals(false, event.isCancelled()); last.setInvokedForCancelled(true); agent.call(this, event); // first should have cancelled event, high ignores cancel, watcher is always run. assertEquals(3, callResults.size()); } @Test public void testEventUncancel() { final List<String> callResults = new ArrayList<>(10); EventAgent agent = new EventAgent() {}; EventSubscriber<CancelEvent> first = getCancellingSubscriber(callResults) .setPriority(EventSubscriberPriority.FIRST); EventSubscriber<CancelEvent> normal = getSubscriber(callResults) .setPriority(EventSubscriberPriority.NORMAL); EventSubscriber<CancelEvent> last = getUncancellingSubscriber(callResults); last.setInvokedForCancelled(true) .setPriority(EventSubscriberPriority.HIGH); EventSubscriber<CancelEvent> watcher = getSubscriber(callResults) .setPriority(EventSubscriberPriority.WATCHER); agent.addSubscriber(first); agent.addSubscriber(normal); agent.addSubscriber(last); agent.addSubscriber(watcher); CancelEvent event = new CancelEvent(); assertEquals(false, event.isCancelled()); agent.call(this, event); // 1. first should have cancelled event, // 2. normal was skipped, // 3. last ignored cancelled and uncancelled it. // 4. normal was run // 5. watcher is always run assertEquals(4, callResults.size()); } private static class CancelEvent implements ICancellable { boolean isCancelled; @Override public boolean isCancelled() { return isCancelled; } @Override public void setCancelled(boolean isCancelled) { this.isCancelled = isCancelled; } } private <T> EventSubscriber<T> getSubscriber(final Collection<String> results) { return new EventSubscriber<T>() { @Override public void onEvent(@Nullable Object caller, T event) { assertEquals(EventAgentTest.this, caller); results.add(getPriority().name()); } }; } private EventSubscriber<CancelEvent> getCancellingSubscriber(final Collection<String> results) { return new EventSubscriber<CancelEvent>() { @Override public void onEvent(@Nullable Object caller, CancelEvent event) { assertEquals(EventAgentTest.this, caller); results.add(getPriority().name()); event.setCancelled(true); } }; } private <T extends ICancellable> EventSubscriber<T> getUncancellingSubscriber(final Collection<String> results) { return new EventSubscriber<T>() { @Override public void onEvent(@Nullable Object caller, T event) { assertEquals(EventAgentTest.this, caller); results.add(getPriority().name()); event.setCancelled(false); } }; } }