ab3a8a3df09a9c5018b8d971c15a41a9660b9194
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / test / java / org / opendaylight / controller / md / sal / dom / broker / impl / DOMNotificationRouterTest.java
1 /*
2  * Copyright (c) 2018 Inocybe Technologies 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.controller.md.sal.dom.broker.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14
15 import com.google.common.collect.ImmutableSet;
16 import com.google.common.util.concurrent.SettableFuture;
17 import com.google.common.util.concurrent.Uninterruptibles;
18 import java.time.Instant;
19 import java.util.Date;
20 import java.util.Set;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.TimeoutException;
24 import javax.annotation.Nullable;
25 import org.junit.BeforeClass;
26 import org.junit.Test;
27 import org.opendaylight.controller.md.sal.dom.api.DOMEvent;
28 import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
29 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
30 import org.opendaylight.controller.md.sal.dom.spi.DOMNotificationSubscriptionListener;
31 import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
32 import org.opendaylight.yangtools.concepts.ListenerRegistration;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
36 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
37 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
38 import org.opendaylight.yangtools.yang.model.api.Module;
39 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
40 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
41 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
42
43 /**
44  * Unit tests for DOMNotificationRouter.
45  *
46  * @author Thomas Pantelis
47  */
48 public class DOMNotificationRouterTest {
49     private static final ContainerNode BODY = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
50         new NodeIdentifier(QName.create(TestModel.TEST_QNAME.getModule(), "test-notification")))
51             .withChild(ImmutableNodes.leafNode(QName.create(TestModel.TEST_QNAME.getModule(), "value-leaf"), "foo"))
52                 .build();
53     private static final Instant INSTANT = Instant.now();
54
55     private static SchemaPath notificationSchemaPath;
56
57     private final org.opendaylight.mdsal.dom.broker.DOMNotificationRouter mdsalRouter =
58             org.opendaylight.mdsal.dom.broker.DOMNotificationRouter.create(16);
59     private final DOMNotificationRouter legacyRouter =
60             DOMNotificationRouter.create(mdsalRouter, mdsalRouter, mdsalRouter);
61     private final TestLegacyDOMNotificationListener testLegacyListener = new TestLegacyDOMNotificationListener();
62     private final TestMdsalDOMNotificationListener testMdsalListener = new TestMdsalDOMNotificationListener();
63
64     @BeforeClass
65     public static void staticSetup() {
66         final SchemaContext schemaContext = TestModel.createTestContext();
67
68         Module testModule = schemaContext.findModule("odl-datastore-test", TestModel.TEST_QNAME.getRevision()).get();
69         NotificationDefinition notificationDefinition = null;
70         for (NotificationDefinition def: testModule.getNotifications()) {
71             if (def.getQName().getLocalName().equals("test-notification")) {
72                 notificationDefinition = def;
73                 break;
74             }
75         }
76
77         assertNotNull("test-notification not found in " + testModule.getNotifications(), notificationDefinition);
78         notificationSchemaPath = notificationDefinition.getPath();
79     }
80
81     @Test
82     public void testLegacyListenerAndPublish() throws InterruptedException, ExecutionException, TimeoutException {
83         final ListenerRegistration<TestLegacyDOMNotificationListener> reg =
84                 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
85
86         legacyRouter.putNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
87         testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
88
89         legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
90         testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
91
92         legacyRouter.offerNotification(new TestLegacyDOMNotification(), 100, TimeUnit.MILLISECONDS)
93             .get(5, TimeUnit.SECONDS);
94         testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
95
96         legacyRouter.offerNotification(new TestLegacyDOMEvent()).get(5, TimeUnit.SECONDS);
97         testLegacyListener.verifyReceived(notificationSchemaPath, BODY, Date.from(INSTANT));
98
99         reg.close();
100
101         legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
102         testLegacyListener.verifyNotReceived();
103     }
104
105     @Test
106     public void testLegacyListenerAndMdsalPublish()
107             throws InterruptedException, ExecutionException, TimeoutException {
108         legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
109
110         mdsalRouter.offerNotification(new TestMdsalDOMNotification()).get(5, TimeUnit.SECONDS);
111         testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
112
113         mdsalRouter.offerNotification(new TestMdsalDOMEvent()).get(5, TimeUnit.SECONDS);
114         testLegacyListener.verifyReceived(notificationSchemaPath, BODY, Date.from(INSTANT));
115     }
116
117     @Test
118     public void testMdsalListenerAndLegacyPublish()
119             throws InterruptedException, ExecutionException, TimeoutException {
120         mdsalRouter.registerNotificationListener(testMdsalListener, notificationSchemaPath);
121
122         legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
123         testMdsalListener.verifyReceived(notificationSchemaPath, BODY, null);
124
125         legacyRouter.offerNotification(new TestLegacyDOMEvent()).get(5, TimeUnit.SECONDS);
126         testMdsalListener.verifyReceived(notificationSchemaPath, BODY, INSTANT);
127     }
128
129     @Test
130     public void testRegisterSubscriptionListener() throws InterruptedException, ExecutionException, TimeoutException {
131         TestLegacyDOMNotificationSubscriptionListener listener = new TestLegacyDOMNotificationSubscriptionListener();
132         final ListenerRegistration<TestLegacyDOMNotificationSubscriptionListener> subscriptionReg =
133                 legacyRouter.registerSubscriptionListener(listener);
134
135         listener.verifyReceived();
136
137         final ListenerRegistration<TestLegacyDOMNotificationListener> listenerReg =
138                 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
139
140         listener.verifyReceived(notificationSchemaPath);
141
142         listenerReg.close();
143
144         listener.verifyReceived();
145
146         subscriptionReg.close();
147
148         legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
149
150         listener.verifyNotReceived();
151     }
152
153     private static class TestLegacyDOMNotificationListener implements DOMNotificationListener {
154         SettableFuture<DOMNotification> receivedNotification = SettableFuture.create();
155
156         @Override
157         public void onNotification(DOMNotification notification) {
158             receivedNotification.set(notification);
159         }
160
161         void verifyReceived(SchemaPath path, ContainerNode body, @Nullable Date eventTime)
162                 throws InterruptedException, ExecutionException, TimeoutException {
163             final DOMNotification actual = receivedNotification.get(5, TimeUnit.SECONDS);
164             assertEquals(path, actual.getType());
165             assertEquals(body, actual.getBody());
166
167             if (eventTime != null) {
168                 assertTrue("Expected DOMEvent", actual instanceof DOMEvent);
169                 assertEquals(eventTime, ((DOMEvent)actual).getEventTime());
170             } else {
171                 assertFalse("Unexpected DOMEvent", actual instanceof DOMEvent);
172             }
173
174             receivedNotification = SettableFuture.create();
175         }
176
177         void verifyNotReceived() {
178             Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
179             assertFalse("Unexpected notification", receivedNotification.isDone());
180         }
181     }
182
183     private static class TestMdsalDOMNotificationListener
184             implements org.opendaylight.mdsal.dom.api.DOMNotificationListener {
185         SettableFuture<org.opendaylight.mdsal.dom.api.DOMNotification> receivedNotification = SettableFuture.create();
186
187         @Override
188         public void onNotification(org.opendaylight.mdsal.dom.api.DOMNotification notification) {
189             receivedNotification.set(notification);
190         }
191
192         void verifyReceived(SchemaPath path, ContainerNode body, @Nullable Instant eventTime)
193                 throws InterruptedException, ExecutionException, TimeoutException {
194             final org.opendaylight.mdsal.dom.api.DOMNotification actual =
195                     receivedNotification.get(5, TimeUnit.SECONDS);
196             assertEquals(path, actual.getType());
197             assertEquals(body, actual.getBody());
198
199             if (eventTime != null) {
200                 assertTrue("Expected DOMEvent", actual instanceof org.opendaylight.mdsal.dom.api.DOMEvent);
201                 assertEquals(eventTime, ((org.opendaylight.mdsal.dom.api.DOMEvent)actual).getEventInstant());
202             } else {
203                 assertFalse("Unexpected DOMEvent", actual instanceof org.opendaylight.mdsal.dom.api.DOMEvent);
204             }
205
206             receivedNotification = SettableFuture.create();
207         }
208     }
209
210     private static class TestLegacyDOMNotificationSubscriptionListener implements DOMNotificationSubscriptionListener {
211         SettableFuture<Set<SchemaPath>> receivedNotification = SettableFuture.create();
212
213         @Override
214         public void onSubscriptionChanged(Set<SchemaPath> currentTypes) {
215             receivedNotification.set(currentTypes);
216         }
217
218         void verifyReceived(SchemaPath... paths)
219                 throws InterruptedException, ExecutionException, TimeoutException {
220             final Set<SchemaPath> actual = receivedNotification.get(5, TimeUnit.SECONDS);
221             assertEquals(ImmutableSet.copyOf(paths), actual);
222             receivedNotification = SettableFuture.create();
223         }
224
225         void verifyNotReceived() {
226             Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
227             assertFalse("Unexpected notification", receivedNotification.isDone());
228         }
229     }
230
231     private static class TestLegacyDOMNotification implements DOMNotification {
232         @Override
233         public SchemaPath getType() {
234             return notificationSchemaPath;
235         }
236
237         @Override
238         public ContainerNode getBody() {
239             return BODY;
240         }
241     }
242
243     private static class TestLegacyDOMEvent extends TestLegacyDOMNotification implements DOMEvent {
244         @Override
245         public Date getEventTime() {
246             return Date.from(INSTANT);
247         }
248     }
249
250     private static class TestMdsalDOMNotification implements org.opendaylight.mdsal.dom.api.DOMNotification {
251         @Override
252         public SchemaPath getType() {
253             return notificationSchemaPath;
254         }
255
256         @Override
257         public ContainerNode getBody() {
258             return BODY;
259         }
260     }
261
262     private static class TestMdsalDOMEvent extends TestMdsalDOMNotification
263             implements org.opendaylight.mdsal.dom.api.DOMEvent {
264         @Override
265         public Instant getEventInstant() {
266             return INSTANT;
267         }
268     }
269 }