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