4a21a4416edb966f6abd06ac29e68b48a41a9f2a
[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.assertTrue;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17
18 import com.google.common.collect.Multimap;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.lmax.disruptor.PhasedBackoffWaitStrategy;
21 import com.lmax.disruptor.WaitStrategy;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.List;
25 import java.util.concurrent.CountDownLatch;
26 import java.util.concurrent.ExecutorService;
27 import java.util.concurrent.TimeUnit;
28 import org.junit.Test;
29 import org.opendaylight.mdsal.dom.api.DOMNotification;
30 import org.opendaylight.mdsal.dom.api.DOMNotificationListener;
31 import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService;
32 import org.opendaylight.mdsal.dom.spi.DOMNotificationSubscriptionListener;
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
34 import org.opendaylight.yangtools.util.ListenerRegistry;
35 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
36
37 public class DOMNotificationRouterTest extends TestUtils {
38
39     private static final WaitStrategy DEFAULT_STRATEGY = PhasedBackoffWaitStrategy.withLock(
40             1L, 30L, TimeUnit.MILLISECONDS);
41
42     @Test
43     public void create() throws Exception {
44         assertNotNull(DOMNotificationRouter.create(1,1,1,TimeUnit.SECONDS));
45         assertNotNull(DOMNotificationRouter.create(1));
46     }
47
48     @SuppressWarnings("checkstyle:IllegalCatch")
49     @Test
50     public void complexTest() throws Exception {
51         final DOMNotificationSubscriptionListener domNotificationSubscriptionListener =
52                 mock(DOMNotificationSubscriptionListener.class);
53         final CountDownLatch latch = new CountDownLatch(1);
54         final DOMNotificationListener domNotificationListener = new TestListener(latch);
55         final DOMNotificationRouter domNotificationRouter = DOMNotificationRouter.create(1);
56
57         Multimap<SchemaPath, ?> listeners = domNotificationRouter.listeners();
58
59         assertTrue(listeners.isEmpty());
60         assertNotNull(domNotificationRouter.registerNotificationListener(domNotificationListener, SchemaPath.ROOT));
61         assertNotNull(domNotificationRouter.registerNotificationListener(domNotificationListener, SchemaPath.SAME));
62
63         listeners = domNotificationRouter.listeners();
64
65         assertFalse(listeners.isEmpty());
66
67         ListenerRegistry<DOMNotificationSubscriptionListener> subscriptionListeners =
68                 domNotificationRouter.subscriptionListeners();
69
70         assertFalse(subscriptionListeners.getRegistrations().iterator().hasNext());
71         assertNotNull(domNotificationRouter.registerSubscriptionListener(domNotificationSubscriptionListener));
72
73         subscriptionListeners = domNotificationRouter.subscriptionListeners();
74         assertTrue(subscriptionListeners.getRegistrations().iterator().hasNext());
75
76         final DOMNotification domNotification = mock(DOMNotification.class);
77         doReturn("test").when(domNotification).toString();
78         doReturn(SchemaPath.ROOT).when(domNotification).getType();
79         doReturn(TEST_CHILD).when(domNotification).getBody();
80
81         assertNotNull(domNotificationRouter.offerNotification(domNotification));
82
83         try {
84             assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
85             assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
86         } catch (Exception e) {
87             assertTrue(e instanceof UnsupportedOperationException);
88         }
89
90         assertNotNull(domNotificationRouter.putNotification(domNotification));
91     }
92
93     @Test
94     public void offerNotification() throws Exception {
95         final DOMNotificationRouter domNotificationRouter = DOMNotificationRouter.create(1);
96         final DOMNotification domNotification = mock(DOMNotification.class);
97         doReturn(SchemaPath.ROOT).when(domNotification).getType();
98         doReturn(TEST_CHILD).when(domNotification).getBody();
99         assertNotNull(domNotificationRouter.putNotification(domNotification));
100         assertNotNull(domNotificationRouter.offerNotification(domNotification));
101         assertNotNull(domNotificationRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
102     }
103
104     @Test
105     public void testOfferNotificationWithBlocking() throws Exception {
106         final CountDownLatch latch = new CountDownLatch(1);
107         final TestListener testListener = new TestListener(latch);
108         final DOMNotification domNotification = mock(DOMNotification.class);
109         doReturn("test").when(domNotification).toString();
110         doReturn(SchemaPath.ROOT).when(domNotification).getType();
111         doReturn(TEST_CHILD).when(domNotification).getBody();
112
113         try (TestRouter testRouter = new TestRouter(1)) {
114             assertNotNull(testRouter.registerNotificationListener(testListener, SchemaPath.ROOT));
115             assertNotNull(testRouter.registerNotificationListener(testListener, SchemaPath.SAME));
116
117             assertNotEquals(DOMNotificationPublishService.REJECTED,
118                 testRouter.offerNotification(domNotification, 3, TimeUnit.SECONDS));
119             assertTrue("Listener was not notified", latch.await(5, TimeUnit.SECONDS));
120             assertEquals("Received notifications", 1, testListener.getReceivedNotifications().size());
121
122             assertEquals(DOMNotificationPublishService.REJECTED,
123                 testRouter.offerNotification(domNotification, 1, TimeUnit.SECONDS));
124             assertEquals("Received notifications", 1, testListener.getReceivedNotifications().size());
125         }
126     }
127
128     @Test
129     public void close() throws Exception {
130         final DOMNotificationRouter domNotificationRouter = DOMNotificationRouter.create(1);
131         final ExecutorService executor = domNotificationRouter.executor();
132         final ExecutorService observer = domNotificationRouter.observer();
133
134         assertFalse(executor.isShutdown());
135         assertFalse(observer.isShutdown());
136         domNotificationRouter.close();
137         assertTrue(executor.isShutdown());
138         assertTrue(observer.isShutdown());
139     }
140
141     private static class TestListener implements DOMNotificationListener {
142         private final CountDownLatch latch;
143         private final List<DOMNotification>  receivedNotifications = new ArrayList<>();
144
145         TestListener(final CountDownLatch latch) {
146             this.latch = latch;
147         }
148
149         @Override
150         public void onNotification(final DOMNotification notification) {
151             receivedNotifications.add(notification);
152             latch.countDown();
153         }
154
155         public List<DOMNotification> getReceivedNotifications() {
156             return receivedNotifications;
157         }
158     }
159
160     private static class TestRouter extends DOMNotificationRouter {
161         TestRouter(final int queueDepth) {
162             super(queueDepth, DEFAULT_STRATEGY);
163         }
164
165         @Override
166         protected ListenableFuture<? extends Object> tryPublish(final DOMNotification notification,
167                 final Collection<ListenerRegistration<? extends DOMNotificationListener>> subscribers) {
168             return DOMNotificationPublishService.REJECTED;
169         }
170
171         @Override
172         public ListenableFuture<? extends Object> putNotification(final DOMNotification notification)
173                 throws InterruptedException {
174             Thread.sleep(2000);
175             return super.putNotification(notification);
176         }
177     }
178 }