2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.dom.broker;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotEquals;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertSame;
15 import static org.junit.Assert.assertTrue;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.doNothing;
18 import static org.mockito.Mockito.doReturn;
19 import static org.mockito.Mockito.mock;
20 import static org.opendaylight.mdsal.dom.broker.TestUtils.TEST_CHILD;
22 import com.google.common.util.concurrent.ListenableFuture;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.List;
27 import java.util.concurrent.CountDownLatch;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.TimeUnit;
30 import org.junit.Test;
31 import org.opendaylight.mdsal.dom.api.DOMNotification;
32 import org.opendaylight.mdsal.dom.api.DOMNotificationListener;
33 import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService;
34 import org.opendaylight.mdsal.dom.spi.DOMNotificationSubscriptionListener;
35 import org.opendaylight.yangtools.util.ListenerRegistry;
36 import org.opendaylight.yangtools.yang.common.QName;
37 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
39 public class DOMNotificationRouterTest {
41 public void registerNotificationListener() {
42 try (var domNotificationRouter = new DOMNotificationRouter(1024)) {
43 final var domNotificationListener = mock(DOMNotificationListener.class);
45 domNotificationRouter.registerNotificationListener(domNotificationListener,
46 List.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif1"))));
47 assertEquals(1, domNotificationRouter.listeners().size());
49 domNotificationRouter.registerNotificationListener(domNotificationListener,
50 List.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif2")),
51 Absolute.of(QName.create("urn:opendaylight:test-listener", "notif3"))));
52 assertEquals(3, domNotificationRouter.listeners().size());
57 public void registerNotificationListeners() {
58 try (var domNotificationRouter = new DOMNotificationRouter(1024)) {
59 final var domNotificationListener1 = mock(DOMNotificationListener.class);
60 final var domNotificationListener2 = mock(DOMNotificationListener.class);
62 domNotificationRouter.registerNotificationListeners(
63 Map.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif1")), domNotificationListener1,
64 Absolute.of(QName.create("urn:opendaylight:test-listener", "notif2")), domNotificationListener2));
65 assertEquals(2, domNotificationRouter.listeners().size());
69 @SuppressWarnings("checkstyle:IllegalCatch")
71 public void complexTest() throws Exception {
72 final DOMNotificationSubscriptionListener domNotificationSubscriptionListener =
73 mock(DOMNotificationSubscriptionListener.class);
74 doNothing().when(domNotificationSubscriptionListener).onSubscriptionChanged(any());
76 final CountDownLatch latch = new CountDownLatch(1);
77 final DOMNotificationListener domNotificationListener = new TestListener(latch);
78 final DOMNotificationRouter domNotificationRouter = new DOMNotificationRouter(1024);
80 var listeners = domNotificationRouter.listeners();
82 assertTrue(listeners.isEmpty());
83 assertNotNull(domNotificationRouter.registerNotificationListener(domNotificationListener,
84 Absolute.of(TestModel.TEST_QNAME)));
85 assertNotNull(domNotificationRouter.registerNotificationListener(domNotificationListener,
86 Absolute.of(TestModel.TEST2_QNAME)));
88 listeners = domNotificationRouter.listeners();
90 assertFalse(listeners.isEmpty());
92 ListenerRegistry<DOMNotificationSubscriptionListener> subscriptionListeners =
93 domNotificationRouter.subscriptionListeners();
95 assertEquals(0, subscriptionListeners.streamListeners().count());
96 assertNotNull(domNotificationRouter.registerSubscriptionListener(domNotificationSubscriptionListener));
98 subscriptionListeners = domNotificationRouter.subscriptionListeners();
99 assertSame(domNotificationSubscriptionListener,
100 subscriptionListeners.streamListeners().findAny().orElseThrow());
102 final DOMNotification domNotification = mock(DOMNotification.class);
103 doReturn("test").when(domNotification).toString();
104 doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
105 doReturn(TEST_CHILD).when(domNotification).getBody();
107 assertNotNull(domNotificationRouter.offerNotification(domNotification));
110 assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
111 assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
112 } catch (Exception e) {
113 // FIXME: what is the point here?!
114 assertTrue(e instanceof UnsupportedOperationException);
117 assertNotNull(domNotificationRouter.putNotification(domNotification));
121 public void offerNotification() throws Exception {
122 try (var domNotificationRouter = new DOMNotificationRouter(1024)) {
123 final DOMNotification domNotification = mock(DOMNotification.class);
124 doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
125 doReturn(TEST_CHILD).when(domNotification).getBody();
126 assertNotNull(domNotificationRouter.putNotification(domNotification));
127 assertNotNull(domNotificationRouter.offerNotification(domNotification));
128 assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
133 public void testOfferNotificationWithBlocking() throws Exception {
134 final CountDownLatch latch = new CountDownLatch(1);
135 final TestListener testListener = new TestListener(latch);
136 final DOMNotification domNotification = mock(DOMNotification.class);
137 doReturn("test").when(domNotification).toString();
138 doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
139 doReturn(TEST_CHILD).when(domNotification).getBody();
141 try (TestRouter testRouter = new TestRouter(1)) {
142 assertNotNull(testRouter.registerNotificationListener(testListener, Absolute.of(TestModel.TEST_QNAME)));
143 assertNotNull(testRouter.registerNotificationListener(testListener, Absolute.of(TestModel.TEST2_QNAME)));
145 assertNotEquals(DOMNotificationPublishService.REJECTED,
146 testRouter.offerNotification(domNotification, 3, TimeUnit.SECONDS));
147 assertTrue("Listener was not notified", latch.await(5, TimeUnit.SECONDS));
148 assertEquals("Received notifications", 1, testListener.getReceivedNotifications().size());
150 assertEquals(DOMNotificationPublishService.REJECTED,
151 testRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
152 assertEquals("Received notifications", 1, testListener.getReceivedNotifications().size());
157 public void close() throws Exception {
158 final ExecutorService executor;
159 final ExecutorService observer;
161 try (var domNotificationRouter = new DOMNotificationRouter(1024)) {
162 executor = domNotificationRouter.executor();
163 observer = domNotificationRouter.observer();
164 assertFalse(executor.isShutdown());
165 assertFalse(observer.isShutdown());
167 assertTrue(executor.isShutdown());
168 assertTrue(observer.isShutdown());
171 private static class TestListener implements DOMNotificationListener {
172 private final CountDownLatch latch;
173 private final List<DOMNotification> receivedNotifications = new ArrayList<>();
175 TestListener(final CountDownLatch latch) {
180 public void onNotification(final DOMNotification notification) {
181 receivedNotifications.add(notification);
185 public List<DOMNotification> getReceivedNotifications() {
186 return receivedNotifications;
190 private static class TestRouter extends DOMNotificationRouter {
192 private boolean triggerRejected = false;
194 TestRouter(final int queueDepth) {
199 ListenableFuture<? extends Object> publish(final DOMNotification notification,
200 final Collection<Reg<?>> subscribers) {
201 if (triggerRejected) {
205 triggerRejected = true;
206 return super.publish(notification, subscribers);
210 public ListenableFuture<? extends Object> putNotification(final DOMNotification notification)
211 throws InterruptedException {
213 return super.putNotification(notification);