Update listeners in registerNotificationListeners
[mdsal.git] / dom / mdsal-dom-broker / src / test / java / org / opendaylight / mdsal / dom / broker / DOMNotificationRouterTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.dom.broker;
9
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;
21
22 import com.google.common.collect.Multimap;
23 import com.google.common.util.concurrent.ListenableFuture;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.concurrent.CountDownLatch;
29 import java.util.concurrent.ExecutorService;
30 import java.util.concurrent.TimeUnit;
31 import org.junit.Test;
32 import org.opendaylight.mdsal.dom.api.DOMNotification;
33 import org.opendaylight.mdsal.dom.api.DOMNotificationListener;
34 import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService;
35 import org.opendaylight.mdsal.dom.spi.DOMNotificationSubscriptionListener;
36 import org.opendaylight.yangtools.util.ListenerRegistry;
37 import org.opendaylight.yangtools.yang.common.QName;
38 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
39
40 public class DOMNotificationRouterTest {
41
42     @Test
43     public void create() throws Exception {
44         assertNotNull(DOMNotificationRouter.create(1024));
45     }
46
47     @Test
48     public void registerNotificationListener() {
49         final var domNotificationRouter = new DOMNotificationRouter(1024);
50         final var domNotificationListener = mock(DOMNotificationListener.class);
51
52         domNotificationRouter.registerNotificationListener(domNotificationListener,
53             List.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif1"))));
54         assertEquals(1, domNotificationRouter.listeners().size());
55
56         domNotificationRouter.registerNotificationListener(domNotificationListener,
57             List.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif2")),
58                 Absolute.of(QName.create("urn:opendaylight:test-listener", "notif3"))));
59         assertEquals(3, domNotificationRouter.listeners().size());
60     }
61
62     @Test
63     public void registerNotificationListeners() {
64         final var domNotificationRouter = new DOMNotificationRouter(1024);
65         final var domNotificationListener1 = mock(DOMNotificationListener.class);
66         final var domNotificationListener2 = mock(DOMNotificationListener.class);
67
68         domNotificationRouter.registerNotificationListeners(
69             Map.of(Absolute.of(QName.create("urn:opendaylight:test-listener", "notif1")), domNotificationListener1,
70                 Absolute.of(QName.create("urn:opendaylight:test-listener", "notif2")), domNotificationListener2));
71         assertEquals(2, domNotificationRouter.listeners().size());
72     }
73
74     @SuppressWarnings("checkstyle:IllegalCatch")
75     @Test
76     public void complexTest() throws Exception {
77         final DOMNotificationSubscriptionListener domNotificationSubscriptionListener =
78                 mock(DOMNotificationSubscriptionListener.class);
79         doNothing().when(domNotificationSubscriptionListener).onSubscriptionChanged(any());
80
81         final CountDownLatch latch = new CountDownLatch(1);
82         final DOMNotificationListener domNotificationListener = new TestListener(latch);
83         final DOMNotificationRouter domNotificationRouter = DOMNotificationRouter.create(1024);
84
85         Multimap<Absolute, ?> listeners = domNotificationRouter.listeners();
86
87         assertTrue(listeners.isEmpty());
88         assertNotNull(domNotificationRouter.registerNotificationListener(domNotificationListener,
89             Absolute.of(TestModel.TEST_QNAME)));
90         assertNotNull(domNotificationRouter.registerNotificationListener(domNotificationListener,
91             Absolute.of(TestModel.TEST2_QNAME)));
92
93         listeners = domNotificationRouter.listeners();
94
95         assertFalse(listeners.isEmpty());
96
97         ListenerRegistry<DOMNotificationSubscriptionListener> subscriptionListeners =
98                 domNotificationRouter.subscriptionListeners();
99
100         assertEquals(0, subscriptionListeners.streamListeners().count());
101         assertNotNull(domNotificationRouter.registerSubscriptionListener(domNotificationSubscriptionListener));
102
103         subscriptionListeners = domNotificationRouter.subscriptionListeners();
104         assertSame(domNotificationSubscriptionListener,
105             subscriptionListeners.streamListeners().findAny().orElseThrow());
106
107         final DOMNotification domNotification = mock(DOMNotification.class);
108         doReturn("test").when(domNotification).toString();
109         doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
110         doReturn(TEST_CHILD).when(domNotification).getBody();
111
112         assertNotNull(domNotificationRouter.offerNotification(domNotification));
113
114         try {
115             assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
116             assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
117         } catch (Exception e) {
118             // FIXME: what is the point here?!
119             assertTrue(e instanceof UnsupportedOperationException);
120         }
121
122         assertNotNull(domNotificationRouter.putNotification(domNotification));
123     }
124
125     @Test
126     public void offerNotification() throws Exception {
127         final DOMNotificationRouter domNotificationRouter = DOMNotificationRouter.create(1024);
128         final DOMNotification domNotification = mock(DOMNotification.class);
129         doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
130         doReturn(TEST_CHILD).when(domNotification).getBody();
131         assertNotNull(domNotificationRouter.putNotification(domNotification));
132         assertNotNull(domNotificationRouter.offerNotification(domNotification));
133         assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
134     }
135
136     @Test
137     public void testOfferNotificationWithBlocking() throws Exception {
138         final CountDownLatch latch = new CountDownLatch(1);
139         final TestListener testListener = new TestListener(latch);
140         final DOMNotification domNotification = mock(DOMNotification.class);
141         doReturn("test").when(domNotification).toString();
142         doReturn(Absolute.of(TestModel.TEST_QNAME)).when(domNotification).getType();
143         doReturn(TEST_CHILD).when(domNotification).getBody();
144
145         try (TestRouter testRouter = new TestRouter(1)) {
146             assertNotNull(testRouter.registerNotificationListener(testListener, Absolute.of(TestModel.TEST_QNAME)));
147             assertNotNull(testRouter.registerNotificationListener(testListener, Absolute.of(TestModel.TEST2_QNAME)));
148
149             assertNotEquals(DOMNotificationPublishService.REJECTED,
150                 testRouter.offerNotification(domNotification, 3, TimeUnit.SECONDS));
151             assertTrue("Listener was not notified", latch.await(5, TimeUnit.SECONDS));
152             assertEquals("Received notifications", 1, testListener.getReceivedNotifications().size());
153
154             assertEquals(DOMNotificationPublishService.REJECTED,
155                     testRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
156             assertEquals("Received notifications", 1, testListener.getReceivedNotifications().size());
157         }
158     }
159
160     @Test
161     public void close() throws Exception {
162         final DOMNotificationRouter domNotificationRouter = DOMNotificationRouter.create(1024);
163         final ExecutorService executor = domNotificationRouter.executor();
164         final ExecutorService observer = domNotificationRouter.observer();
165
166         assertFalse(executor.isShutdown());
167         assertFalse(observer.isShutdown());
168         domNotificationRouter.close();
169         assertTrue(executor.isShutdown());
170         assertTrue(observer.isShutdown());
171     }
172
173     private static class TestListener implements DOMNotificationListener {
174         private final CountDownLatch latch;
175         private final List<DOMNotification>  receivedNotifications = new ArrayList<>();
176
177         TestListener(final CountDownLatch latch) {
178             this.latch = latch;
179         }
180
181         @Override
182         public void onNotification(final DOMNotification notification) {
183             receivedNotifications.add(notification);
184             latch.countDown();
185         }
186
187         public List<DOMNotification> getReceivedNotifications() {
188             return receivedNotifications;
189         }
190     }
191
192     private static class TestRouter extends DOMNotificationRouter {
193
194         private boolean triggerRejected = false;
195
196         TestRouter(final int queueDepth) {
197             super(queueDepth);
198         }
199
200         @Override
201         ListenableFuture<? extends Object> publish(final DOMNotification notification,
202                 final Collection<Reg<?>> subscribers) {
203             if (triggerRejected) {
204                 return REJECTED;
205             }
206
207             triggerRejected = true;
208             return super.publish(notification, subscribers);
209         }
210
211         @Override
212         public ListenableFuture<? extends Object> putNotification(final DOMNotification notification)
213                 throws InterruptedException {
214             Thread.sleep(2000);
215             return super.putNotification(notification);
216         }
217     }
218 }