This is an automated email from the ASF dual-hosted git repository.
timothyjward pushed a commit to branch feature/v1.1
in repository https://gitbox.apache.org/repos/asf/aries-typedevent.git
The following commit(s) were added to refs/heads/feature/v1.1 by this push:
new a0c02c9 Fix bug in whiteboard service update/remove
a0c02c9 is described below
commit a0c02c9e8dea7a5aa48e5fc42a89b433df130087
Author: Tim Ward <[email protected]>
AuthorDate: Fri Sep 15 16:05:46 2023 +0100
Fix bug in whiteboard service update/remove
The removal code did not correctly clear instances from the type specific
id maps, or from the wildcard maps. This commit adds a test for the failing
case and also fixes the map management logic.
Signed-off-by: Tim Ward <[email protected]>
---
.../typedevent/bus/impl/TypedEventBusImpl.java | 20 ++--
.../bus/osgi/EventDeliveryIntegrationTest.java | 101 ++++++++++++++++++++-
2 files changed, 113 insertions(+), 8 deletions(-)
diff --git
a/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImpl.java
b/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImpl.java
index e221e2f..5c58047 100644
---
a/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImpl.java
+++
b/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImpl.java
@@ -278,7 +278,7 @@ public class TypedEventBusImpl implements TypedEventBus {
} else {
mapToUse = map;
topicToUse = s;
- selector = new EventSelector(s, f);
+ selector = new EventSelector(null, f);
}
Map<T, EventSelector> handlers =
mapToUse.computeIfAbsent(topicToUse, x1 -> new HashMap<>());
handlers.put(handler, selector);
@@ -294,7 +294,7 @@ public class TypedEventBusImpl implements TypedEventBus {
Long serviceId = getServiceId(properties);
- doRemoveEventHandler(topicsToTypedHandlers, knownTypedHandlers,
handler, serviceId);
+ doRemoveEventHandler(topicsToTypedHandlers,
wildcardTopicsToTypedHandlers, knownTypedHandlers, handler, serviceId);
synchronized (lock) {
typedHandlersToTargetClasses.remove(handler);
@@ -305,7 +305,7 @@ public class TypedEventBusImpl implements TypedEventBus {
Long serviceId = getServiceId(properties);
- doRemoveEventHandler(topicsToUntypedHandlers, knownUntypedHandlers,
handler, serviceId);
+ doRemoveEventHandler(topicsToUntypedHandlers,
wildcardTopicsToUntypedHandlers, knownUntypedHandlers, handler, serviceId);
}
private Long getServiceId(Map<String, Object> properties) {
@@ -330,14 +330,20 @@ public class TypedEventBusImpl implements TypedEventBus {
}
}
- private <T, U> void doRemoveEventHandler(Map<String, Map<T, U>> map,
Map<Long, T> idMap,
+ private <T, U> void doRemoveEventHandler(Map<String, Map<T, U>> map,
Map<String, Map<T, U>> wildcardMap, Map<Long, T> idMap,
T handler, Long serviceId) {
synchronized (lock) {
List<String> consumed = knownHandlers.remove(serviceId);
- knownHandlers.remove(serviceId);
+ idMap.remove(serviceId);
if (consumed != null) {
consumed.forEach(s -> {
- Map<T, ?> handlers = map.get(s);
+ Map<T, ?> handlers;
+ if(isWildcard(s)) {
+ handlers = wildcardMap.get(new EventSelector(s,
null).getInitial());
+ } else {
+ handlers = map.get(s);
+ }
+
if (handlers != null) {
handlers.remove(handler);
if (handlers.isEmpty()) {
@@ -373,7 +379,7 @@ public class TypedEventBusImpl implements TypedEventBus {
synchronized (lock) {
T handler = idToHandler.get(serviceId);
- doRemoveEventHandler(map, idToHandler, handler, serviceId);
+ doRemoveEventHandler(map, wildcardMap, idToHandler, handler,
serviceId);
doAddEventHandler(map, wildcardMap, idToHandler, handler,
defaultTopic, properties,
(a,b) -> new EventTask() {
@Override
diff --git
a/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/osgi/EventDeliveryIntegrationTest.java
b/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/osgi/EventDeliveryIntegrationTest.java
index d435b7a..d77a6a6 100644
---
a/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/osgi/EventDeliveryIntegrationTest.java
+++
b/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/osgi/EventDeliveryIntegrationTest.java
@@ -18,6 +18,7 @@ package org.apache.aries.typedevent.bus.osgi;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
+import static
org.osgi.service.typedevent.TypedEventConstants.TYPED_EVENT_TOPICS;
import java.util.Dictionary;
import java.util.HashMap;
@@ -211,6 +212,104 @@ public class EventDeliveryIntegrationTest extends
AbstractIntegrationTest {
assertEquals("foo", received.subEvent.message);
}
-
+ /**
+ * Tests that events are delivered to untyped Event Handlers
+ * based on topic
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ public void testEventReceivingUpdateTopic() throws InterruptedException {
+
+ TestEvent event = new TestEvent();
+ event.message = "boo";
+
+ Dictionary<String, Object> props = new Hashtable<>();
+ props.put(TYPED_EVENT_TOPICS, TEST_EVENT_TOPIC);
+
+ regs.add(context.registerService(TypedEventHandler.class,
typedEventHandler, props));
+
+ regs.add(context.registerService(UntypedEventHandler.class,
untypedEventHandler, props));
+
+ eventBus.deliver(event);
+
+ Mockito.verify(typedEventHandler, Mockito.timeout(1000)).notify(
+ Mockito.eq(TEST_EVENT_TOPIC),
Mockito.argThat(isTestEventWithMessage("boo")));
+
+ Mockito.verify(untypedEventHandler,
Mockito.timeout(1000)).notifyUntyped(
+ Mockito.eq(TEST_EVENT_TOPIC),
Mockito.argThat(isUntypedTestEventWithMessage("boo")));
+
+ Mockito.clearInvocations(typedEventHandler, untypedEventHandler);
+
+ props.put(TYPED_EVENT_TOPICS, TEST_EVENT_2_TOPIC);
+
+ regs.forEach(s -> s.setProperties(props));
+
+ eventBus.deliver(event);
+
+ Mockito.verify(typedEventHandler, Mockito.after(1000).never()).notify(
+ Mockito.eq(TEST_EVENT_TOPIC), Mockito.any());
+ Mockito.verify(untypedEventHandler,
Mockito.after(1000).never()).notifyUntyped(
+ Mockito.eq(TEST_EVENT_TOPIC), Mockito.any());
+
+ eventBus.deliver(TEST_EVENT_2_TOPIC, event);
+
+ Mockito.verify(typedEventHandler, Mockito.timeout(1000)).notify(
+ Mockito.eq(TEST_EVENT_2_TOPIC),
Mockito.argThat(isTestEventWithMessage("boo")));
+
+ Mockito.verify(untypedEventHandler,
Mockito.timeout(1000)).notifyUntyped(
+ Mockito.eq(TEST_EVENT_2_TOPIC),
Mockito.argThat(isUntypedTestEventWithMessage("boo")));
+
+ }
+
+ /**
+ * Tests that events are delivered to untyped Event Handlers
+ * based on topic
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ public void testEventReceivingUpdateWildcardTopic() throws
InterruptedException {
+
+ TestEvent event = new TestEvent();
+ event.message = "boo";
+
+ Dictionary<String, Object> props = new Hashtable<>();
+ props.put(TYPED_EVENT_TOPICS, "foo/+/foobar");
+
+ regs.add(context.registerService(TypedEventHandler.class,
typedEventHandler, props));
+
+ regs.add(context.registerService(UntypedEventHandler.class,
untypedEventHandler, props));
+
+ eventBus.deliver("foo/bar/foobar", event);
+
+ Mockito.verify(typedEventHandler, Mockito.timeout(1000)).notify(
+ Mockito.eq("foo/bar/foobar"),
Mockito.argThat(isTestEventWithMessage("boo")));
+
+ Mockito.verify(untypedEventHandler,
Mockito.timeout(1000)).notifyUntyped(
+ Mockito.eq("foo/bar/foobar"),
Mockito.argThat(isUntypedTestEventWithMessage("boo")));
+
+ Mockito.clearInvocations(typedEventHandler, untypedEventHandler);
+
+ props.put(TYPED_EVENT_TOPICS, "foo/bar/foobar/+");
+
+ regs.forEach(s -> s.setProperties(props));
+
+ eventBus.deliver("foo/bar/foobar", event);
+
+ Mockito.verify(typedEventHandler, Mockito.after(1000).never()).notify(
+ Mockito.eq("foo/bar/foobar"), Mockito.any());
+ Mockito.verify(untypedEventHandler,
Mockito.after(1000).never()).notifyUntyped(
+ Mockito.eq("foo/bar/foobar"), Mockito.any());
+
+ eventBus.deliver("foo/bar/foobar/fizzbuzz", event);
+
+ Mockito.verify(typedEventHandler, Mockito.timeout(1000)).notify(
+ Mockito.eq("foo/bar/foobar/fizzbuzz"),
Mockito.argThat(isTestEventWithMessage("boo")));
+
+ Mockito.verify(untypedEventHandler,
Mockito.timeout(1000)).notifyUntyped(
+ Mockito.eq("foo/bar/foobar/fizzbuzz"),
Mockito.argThat(isUntypedTestEventWithMessage("boo")));
+
+ }
}
\ No newline at end of file