2 * Copyright (c) 2018 Inocybe Technologies 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.controller.md.sal.dom.broker.impl;
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;
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;
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;
45 * Unit tests for DOMNotificationRouter.
47 * @author Thomas Pantelis
49 public class DOMNotificationRouterTest {
50 private static final ContainerNode BODY = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
51 new NodeIdentifier(QName.create(TestModel.TEST_QNAME.getModule(), "test-notification")))
52 .withChild(ImmutableNodes.leafNode(QName.create(TestModel.TEST_QNAME.getModule(), "value-leaf"), "foo"))
54 // Truncate to milliseconds, as Java 9+ we get microsecond precision, which cannot be expressed in terms of Date
55 private static final Instant INSTANT = Instant.now().truncatedTo(ChronoUnit.MILLIS);
57 private static SchemaPath notificationSchemaPath;
59 private final org.opendaylight.mdsal.dom.broker.DOMNotificationRouter mdsalRouter =
60 org.opendaylight.mdsal.dom.broker.DOMNotificationRouter.create(16);
61 private final DOMNotificationRouter legacyRouter =
62 DOMNotificationRouter.create(mdsalRouter, mdsalRouter, mdsalRouter);
63 private final TestLegacyDOMNotificationListener testLegacyListener = new TestLegacyDOMNotificationListener();
64 private final TestMdsalDOMNotificationListener testMdsalListener = new TestMdsalDOMNotificationListener();
67 public static void staticSetup() {
68 final SchemaContext schemaContext = TestModel.createTestContext();
70 Module testModule = schemaContext.findModule("odl-datastore-test", TestModel.TEST_QNAME.getRevision()).get();
71 NotificationDefinition notificationDefinition = null;
72 for (NotificationDefinition def: testModule.getNotifications()) {
73 if (def.getQName().getLocalName().equals("test-notification")) {
74 notificationDefinition = def;
79 assertNotNull("test-notification not found in " + testModule.getNotifications(), notificationDefinition);
80 notificationSchemaPath = notificationDefinition.getPath();
84 public void testLegacyListenerAndPublish() throws InterruptedException, ExecutionException, TimeoutException {
85 final ListenerRegistration<TestLegacyDOMNotificationListener> reg =
86 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
88 legacyRouter.putNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
89 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
91 legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
92 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
94 legacyRouter.offerNotification(new TestLegacyDOMNotification(), 100, TimeUnit.MILLISECONDS)
95 .get(5, TimeUnit.SECONDS);
96 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
98 legacyRouter.offerNotification(new TestLegacyDOMEvent()).get(5, TimeUnit.SECONDS);
99 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, Date.from(INSTANT));
103 legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
104 testLegacyListener.verifyNotReceived();
108 public void testLegacyListenerAndMdsalPublish()
109 throws InterruptedException, ExecutionException, TimeoutException {
110 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
112 mdsalRouter.offerNotification(new TestMdsalDOMNotification()).get(5, TimeUnit.SECONDS);
113 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
115 mdsalRouter.offerNotification(new TestMdsalDOMEvent()).get(5, TimeUnit.SECONDS);
116 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, Date.from(INSTANT));
120 public void testMdsalListenerAndLegacyPublish()
121 throws InterruptedException, ExecutionException, TimeoutException {
122 mdsalRouter.registerNotificationListener(testMdsalListener, notificationSchemaPath);
124 legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
125 testMdsalListener.verifyReceived(notificationSchemaPath, BODY, null);
127 legacyRouter.offerNotification(new TestLegacyDOMEvent()).get(5, TimeUnit.SECONDS);
128 testMdsalListener.verifyReceived(notificationSchemaPath, BODY, INSTANT);
132 public void testRegisterSubscriptionListener() throws InterruptedException, ExecutionException, TimeoutException {
133 TestLegacyDOMNotificationSubscriptionListener listener = new TestLegacyDOMNotificationSubscriptionListener();
134 final ListenerRegistration<TestLegacyDOMNotificationSubscriptionListener> subscriptionReg =
135 legacyRouter.registerSubscriptionListener(listener);
137 listener.verifyReceived();
139 final ListenerRegistration<TestLegacyDOMNotificationListener> listenerReg =
140 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
142 listener.verifyReceived(notificationSchemaPath);
146 listener.verifyReceived();
148 subscriptionReg.close();
150 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
152 listener.verifyNotReceived();
155 private static class TestLegacyDOMNotificationListener implements DOMNotificationListener {
156 SettableFuture<DOMNotification> receivedNotification = SettableFuture.create();
159 public void onNotification(final DOMNotification notification) {
160 receivedNotification.set(notification);
163 void verifyReceived(final SchemaPath path, final ContainerNode body, final @Nullable Date eventTime)
164 throws InterruptedException, ExecutionException, TimeoutException {
165 final DOMNotification actual = receivedNotification.get(5, TimeUnit.SECONDS);
166 assertEquals(path, actual.getType());
167 assertEquals(body, actual.getBody());
169 if (eventTime != null) {
170 assertTrue("Expected DOMEvent", actual instanceof DOMEvent);
171 assertEquals(eventTime, ((DOMEvent)actual).getEventTime());
173 assertFalse("Unexpected DOMEvent", actual instanceof DOMEvent);
176 receivedNotification = SettableFuture.create();
179 void verifyNotReceived() {
180 Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
181 assertFalse("Unexpected notification", receivedNotification.isDone());
185 private static class TestMdsalDOMNotificationListener
186 implements org.opendaylight.mdsal.dom.api.DOMNotificationListener {
187 SettableFuture<org.opendaylight.mdsal.dom.api.DOMNotification> receivedNotification = SettableFuture.create();
190 public void onNotification(final org.opendaylight.mdsal.dom.api.DOMNotification notification) {
191 receivedNotification.set(notification);
194 void verifyReceived(final SchemaPath path, final ContainerNode body, final @Nullable Instant eventTime)
195 throws InterruptedException, ExecutionException, TimeoutException {
196 final org.opendaylight.mdsal.dom.api.DOMNotification actual =
197 receivedNotification.get(5, TimeUnit.SECONDS);
198 assertEquals(path, actual.getType());
199 assertEquals(body, actual.getBody());
201 if (eventTime != null) {
202 assertTrue("Expected DOMEvent", actual instanceof org.opendaylight.mdsal.dom.api.DOMEvent);
203 assertEquals(eventTime, ((org.opendaylight.mdsal.dom.api.DOMEvent)actual).getEventInstant());
205 assertFalse("Unexpected DOMEvent", actual instanceof org.opendaylight.mdsal.dom.api.DOMEvent);
208 receivedNotification = SettableFuture.create();
212 private static class TestLegacyDOMNotificationSubscriptionListener implements DOMNotificationSubscriptionListener {
213 SettableFuture<Set<SchemaPath>> receivedNotification = SettableFuture.create();
216 public void onSubscriptionChanged(final Set<SchemaPath> currentTypes) {
217 receivedNotification.set(currentTypes);
220 void verifyReceived(final SchemaPath... paths)
221 throws InterruptedException, ExecutionException, TimeoutException {
222 final Set<SchemaPath> actual = receivedNotification.get(5, TimeUnit.SECONDS);
223 assertEquals(ImmutableSet.copyOf(paths), actual);
224 receivedNotification = SettableFuture.create();
227 void verifyNotReceived() {
228 Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
229 assertFalse("Unexpected notification", receivedNotification.isDone());
233 private static class TestLegacyDOMNotification implements DOMNotification {
235 public SchemaPath getType() {
236 return notificationSchemaPath;
240 public ContainerNode getBody() {
245 private static class TestLegacyDOMEvent extends TestLegacyDOMNotification implements DOMEvent {
247 public Date getEventTime() {
248 return Date.from(INSTANT);
252 private static class TestMdsalDOMNotification implements org.opendaylight.mdsal.dom.api.DOMNotification {
254 public SchemaPath getType() {
255 return notificationSchemaPath;
259 public ContainerNode getBody() {
264 private static class TestMdsalDOMEvent extends TestMdsalDOMNotification
265 implements org.opendaylight.mdsal.dom.api.DOMEvent {
267 public Instant getEventInstant() {