Archived
0

update test EventBus

This commit is contained in:
2019-03-25 14:09:13 +03:00
parent 6057746178
commit 5b91ca72c5
3 changed files with 291 additions and 139 deletions

View File

@@ -9,6 +9,7 @@ import org.slf4j.helpers.MessageFormatter;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -25,9 +26,11 @@ public class EventBus {
private Stream<Method> getMethods(Object subscriberObject) { private Stream<Method> getMethods(Object subscriberObject) {
return Stream.of(subscriberObject.getClass().getDeclaredMethods()) return Stream.of(subscriberObject.getClass().getDeclaredMethods())
.filter(method -> method.isAnnotationPresent(Subscriber.class)) .filter(method -> method.isAnnotationPresent(Subscriber.class))
.filter(method -> !Modifier.isPrivate(method.getModifiers()))
.filter(method -> method.getReturnType().equals(Void.TYPE)) .filter(method -> method.getReturnType().equals(Void.TYPE))
.filter(method -> method.getParameterCount() == 1) .filter(method -> method.getParameterCount() == 1)
.filter(method -> Event.class.isAssignableFrom(method.getParameterTypes()[0])); .filter(method -> Event.class.isAssignableFrom(method.getParameterTypes()[0]))
.filter(method -> method.getParameterTypes()[0] != Event.class);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -63,25 +66,25 @@ public class EventBus {
} }
public void post(Event event) { public void post(Event event) {
eventQueue.add(event); if (subscribes.containsKey(event.getClass())) {
eventQueue.add(event);
}
} }
public void process() { public void process() {
Event event; Event event;
while ((event = eventQueue.poll()) != null) { while ((event = eventQueue.poll()) != null) {
final Class<? extends Event> type = event.getClass(); final Class<? extends Event> type = event.getClass();
if (subscribes.containsKey(type)) { final List<Pair<Object, Method>> pairs = subscribes.get(type);
final List<Pair<Object, Method>> pairs = subscribes.get(type); for (Pair<Object, Method> pair : pairs) {
for (Pair<Object, Method> pair : pairs) { try {
try { pair.getValue().invoke(pair.getKey(), event);
pair.getValue().invoke(pair.getKey(), event); } catch (IllegalAccessException | InvocationTargetException e) {
} catch (IllegalAccessException | InvocationTargetException e) { log.error(MessageFormatter.format("Invoke method '{}#{}'",
log.error(MessageFormatter.format("Invoke method '{}#{}'", pair.getKey().getClass().getSimpleName(),
pair.getKey().getClass().getSimpleName(), pair.getValue().getName()).getMessage(),
pair.getValue().getName()).getMessage(), e
e );
);
}
} }
} }
} }

View File

@@ -1,125 +0,0 @@
package mc.core;
import javafx.util.Pair;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import mc.core.eventbus.Event;
import mc.core.eventbus.EventBus;
import mc.core.eventbus.Subscriber;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.internal.util.reflection.Whitebox;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
class TestEventBus {
private List<String> resultList = new ArrayList<>();
@SuppressWarnings("unchecked")
private Map<Class<? extends Event>, List<Pair<Object, Method>>> getEventBusFieldSubscribes() {
return (Map<Class<? extends Event>, List<Pair<Object, Method>>>)
Whitebox.getInternalState(EventBus.getInstance(), "subscribes");
}
@BeforeEach
@SuppressWarnings("unchecked")
void before() {
getEventBusFieldSubscribes().clear();
((Queue<Event>) Whitebox.getInternalState(EventBus.getInstance(), "eventQueue")).clear();
}
@Test
void testRegisterSubscribes() {
DumbEventHandler handler = new DumbEventHandler();
EventBus.getInstance().registerSubscribes(handler);
Map<Class<? extends Event>, List<Pair<Object, Method>>> subscribes = getEventBusFieldSubscribes();
assertEquals(1, subscribes.size());
List<Pair<Object, Method>> pairs = subscribes.values().iterator().next();
assertEquals(1, pairs.size());
Pair<Object, Method> pair = pairs.get(0);
assertSame(handler, pair.getKey());
assertEquals("corectSubscribe", pair.getValue().getName());
}
@Test
void testUnregisterSubscribes() {
DumbEventHandler handler = new DumbEventHandler();
EventBus.getInstance().registerSubscribes(handler);
EventBus.getInstance().unregisterSubscribes(handler);
Map<Class<? extends Event>, List<Pair<Object, Method>>> subscribes = getEventBusFieldSubscribes();
assertEquals(0, subscribes.size());
}
@Test
@SuppressWarnings("unchecked")
void testPost() {
EventBus.getInstance().post(new DumbEvent());
Queue<Event> eventQueue = (Queue<Event>) Whitebox.getInternalState(EventBus.getInstance(), "eventQueue");
assertEquals(1, eventQueue.size());
}
@Test
void testProcess() {
Stream.of(new DumbEventHandler("D1 "), new DumbEventHandler("D2 "))
.forEach(handler -> EventBus.getInstance().registerSubscribes(handler));
Stream.of(new DumbEvent("message 1"), new DumbEvent("message 2"))
.forEach(event -> EventBus.getInstance().post(event));
EventBus.getInstance().process();
assertEquals(4, resultList.size());
assertEquals("D1 message 1", resultList.get(0));
assertEquals("D2 message 1", resultList.get(1));
assertEquals("D1 message 2", resultList.get(2));
assertEquals("D2 message 2", resultList.get(3));
}
@AllArgsConstructor
@NoArgsConstructor
private class DumbEvent implements Event {
String message;
}
@AllArgsConstructor
@NoArgsConstructor
public class DumbEventHandler {
private String prefix = "";
@Subscriber
public void corectSubscribe(DumbEvent event) {
resultList.add(prefix + event.message);
}
@Subscriber
public Object incorectSubscribeReturnType(DumbEvent event) {
return null;
}
@Subscriber
public void incorrectSubscriberTypeParameter(Object object) {
}
@Subscriber
public void incorrectSubscriberManyParameters(DumbEvent event, Object object) {
}
public void someMethod() {
}
}
}

View File

@@ -0,0 +1,274 @@
package mc.core.eventbus;
import javafx.util.Pair;
import lombok.AllArgsConstructor;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.internal.util.reflection.Whitebox;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.*;
class EventBusTest {
private EventBus eventBus = EventBus.getInstance();
@AfterEach
void after() {
getEventQueue().clear();
getSubscribes().clear();
}
@Test
void testRegisterSubscribes() {
final AbstractDumpEventHandler handler = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe(DumbEvent event) {
}
};
eventBus.registerSubscribes(handler);
assertEquals(1, getSubscribes().size());
assertTrue(getSubscribes().containsKey(DumbEvent.class));
assertNotNull(getSubscribes().get(DumbEvent.class));
assertEquals(1, getSubscribes().get(DumbEvent.class).size());
}
@Test
void testRegisterSubscribesManyHandlers() {
final AbstractDumpEventHandler handler1 = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe(DumbEvent event) {
result += event.message;
}
};
final AbstractDumpEventHandler handler2 = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe(DumbEvent event) {
result += event.message;
}
};
eventBus.registerSubscribes(handler1);
eventBus.registerSubscribes(handler2);
assertEquals(1, getSubscribes().size());
assertTrue(getSubscribes().containsKey(DumbEvent.class));
assertNotNull(getSubscribes().get(DumbEvent.class));
assertEquals(2, getSubscribes().get(DumbEvent.class).size());
}
private static Stream<Arguments> streamIncorrectRegisterSubscribes() {
return Stream.of(
Arguments.of(new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
public void incorectSubscribe(DumbEvent event) {
result += event.message;
}
}),
Arguments.of(new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
private void incorectSubscribe(DumbEvent event) {
result += event.message;
}
}),
Arguments.of(new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public Object incorectSubscribe(DumbEvent event) {
result += event.message;
return null;
}
}),
Arguments.of(new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void incorectSubscribe(DumbEvent event, DumbEvent ev2) {
result += "Any";
}
}),
Arguments.of(new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void incorectSubscribe(Object event) {
result += "Any";
}
}),
Arguments.of(new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void incorectSubscribe(Event event) {
result += "Any";
}
})
);
}
@ParameterizedTest
@MethodSource("streamIncorrectRegisterSubscribes")
void testIncorrectRegisterSubscribes(AbstractDumpEventHandler incorrectHandler) {
eventBus.registerSubscribes(incorrectHandler);
assertEquals(0, getSubscribes().size());
}
@Test
void testUnregisterSubscribes() {
final AbstractDumpEventHandler handler1 = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe1(DumbEvent event) {
result += event.message;
}
};
final AbstractDumpEventHandler handler2 = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe2(DumbEvent event) {
result += event.message;
}
};
eventBus.registerSubscribes(handler1);
eventBus.registerSubscribes(handler2);
eventBus.unregisterSubscribes(handler1);
assertEquals(1, getSubscribes().size());
assertTrue(getSubscribes().containsKey(DumbEvent.class));
assertNotNull(getSubscribes().get(DumbEvent.class));
assertEquals(1, getSubscribes().get(DumbEvent.class).size());
assertEquals("corectSubscribe2", getSubscribes().get(DumbEvent.class).get(0).getValue().getName());
}
@Test
void testUnregisterSubscribesNotExistsEvent() {
final AbstractDumpEventHandler handler1 = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe1(DumbEvent event) {
result += event.message;
}
};
eventBus.registerSubscribes(handler1);
final AbstractDumpEventHandler handler2 = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe2(DumbEvent2 event) {
result += "Any";
}
};
eventBus.unregisterSubscribes(handler2);
assertEquals(1, getSubscribes().size());
assertTrue(getSubscribes().containsKey(DumbEvent.class));
assertNotNull(getSubscribes().get(DumbEvent.class));
assertEquals(1, getSubscribes().get(DumbEvent.class).size());
assertEquals("corectSubscribe1", getSubscribes().get(DumbEvent.class).get(0).getValue().getName());
}
@Test
void testUnregisterSubscribesLast() {
final AbstractDumpEventHandler handler = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe(DumbEvent event) {
result += event.message;
}
};
eventBus.registerSubscribes(handler);
eventBus.unregisterSubscribes(handler);
assertEquals(0, getSubscribes().size());
}
@Test
void testPost() {
final AbstractDumpEventHandler handler = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe(DumbEvent event) {
result += event.message;
}
};
eventBus.registerSubscribes(handler);
final DumbEvent event = new DumbEvent("Hello?");
eventBus.post(event);
eventBus.post(event);
eventBus.post(event);
final Queue<Event> eventQueue = getEventQueue();
assertEquals(3, eventQueue.size());
assertEquals(event, eventQueue.peek());
}
@Test
void testPostNoHandlerEvent() {
final DumbEvent event = new DumbEvent("Hello?");
eventBus.post(event);
final Queue<Event> eventQueue = getEventQueue();
assertTrue(eventQueue.isEmpty());
}
@Test
void testProcess() {
final AbstractDumpEventHandler handler = new AbstractDumpEventHandler() {
@SuppressWarnings("unused")
@Subscriber
public void corectSubscribe(DumbEvent event) {
result += event.message;
}
};
eventBus.registerSubscribes(handler);
eventBus.post(new DumbEvent("Hello?"));
eventBus.process();
assertTrue(getEventQueue().isEmpty());
assertEquals("Hello?", handler.result);
}
@SuppressWarnings("unchecked")
private Map<Class<? extends Event>, List<Pair<Object, Method>>> getSubscribes() {
return (Map<Class<? extends Event>, List<Pair<Object, Method>>>)
Whitebox.getInternalState(eventBus, "subscribes");
}
@SuppressWarnings("unchecked")
private Queue<Event> getEventQueue() {
return (Queue<Event>)
Whitebox.getInternalState(eventBus, "eventQueue");
}
@AllArgsConstructor
private class DumbEvent implements Event {
String message;
}
private class DumbEvent2 implements Event {
}
private static abstract class AbstractDumpEventHandler {
String result = "";
}
}