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
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"))
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);
58 private static SchemaPath notificationSchemaPath;
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();
68 public static void staticSetup() {
69 final SchemaContext schemaContext = TestModel.createTestContext();
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;
80 assertNotNull("test-notification not found in " + testModule.getNotifications(), notificationDefinition);
81 notificationSchemaPath = notificationDefinition.getPath();
85 public void testLegacyListenerAndPublish() throws InterruptedException, ExecutionException, TimeoutException {
86 final ListenerRegistration<TestLegacyDOMNotificationListener> reg =
87 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
89 legacyRouter.putNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
90 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
92 legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
93 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
95 legacyRouter.offerNotification(new TestLegacyDOMNotification(), 100, TimeUnit.MILLISECONDS)
96 .get(5, TimeUnit.SECONDS);
97 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
99 legacyRouter.offerNotification(new TestLegacyDOMEvent()).get(5, TimeUnit.SECONDS);
100 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, Date.from(INSTANT));
104 legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
105 testLegacyListener.verifyNotReceived();
109 public void testLegacyListenerAndMdsalPublish()
110 throws InterruptedException, ExecutionException, TimeoutException {
111 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
113 mdsalRouter.offerNotification(new TestMdsalDOMNotification()).get(5, TimeUnit.SECONDS);
114 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, null);
116 mdsalRouter.offerNotification(new TestMdsalDOMEvent()).get(5, TimeUnit.SECONDS);
117 testLegacyListener.verifyReceived(notificationSchemaPath, BODY, Date.from(INSTANT));
121 public void testMdsalListenerAndLegacyPublish()
122 throws InterruptedException, ExecutionException, TimeoutException {
123 mdsalRouter.registerNotificationListener(testMdsalListener, notificationSchemaPath);
125 legacyRouter.offerNotification(new TestLegacyDOMNotification()).get(5, TimeUnit.SECONDS);
126 testMdsalListener.verifyReceived(notificationSchemaPath, BODY, null);
128 legacyRouter.offerNotification(new TestLegacyDOMEvent()).get(5, TimeUnit.SECONDS);
129 testMdsalListener.verifyReceived(notificationSchemaPath, BODY, INSTANT);
133 public void testRegisterSubscriptionListener() throws InterruptedException, ExecutionException, TimeoutException {
134 TestLegacyDOMNotificationSubscriptionListener listener = new TestLegacyDOMNotificationSubscriptionListener();
135 final ListenerRegistration<TestLegacyDOMNotificationSubscriptionListener> subscriptionReg =
136 legacyRouter.registerSubscriptionListener(listener);
138 listener.verifyReceived();
140 final ListenerRegistration<TestLegacyDOMNotificationListener> listenerReg =
141 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
143 listener.verifyReceived(notificationSchemaPath);
147 listener.verifyReceived();
149 subscriptionReg.close();
151 legacyRouter.registerNotificationListener(testLegacyListener, notificationSchemaPath);
153 listener.verifyNotReceived();
156 private static class TestLegacyDOMNotificationListener implements DOMNotificationListener {
157 SettableFuture<DOMNotification> receivedNotification = SettableFuture.create();
160 public void onNotification(final DOMNotification notification) {
161 receivedNotification.set(notification);
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());
170 if (eventTime != null) {
171 assertTrue("Expected DOMEvent", actual instanceof DOMEvent);
172 assertEquals(eventTime, ((DOMEvent)actual).getEventTime());
174 assertFalse("Unexpected DOMEvent", actual instanceof DOMEvent);
177 receivedNotification = SettableFuture.create();
180 void verifyNotReceived() {
181 Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
182 assertFalse("Unexpected notification", receivedNotification.isDone());
186 private static class TestMdsalDOMNotificationListener
187 implements org.opendaylight.mdsal.dom.api.DOMNotificationListener {
188 SettableFuture<org.opendaylight.mdsal.dom.api.DOMNotification> receivedNotification = SettableFuture.create();
191 public void onNotification(final org.opendaylight.mdsal.dom.api.DOMNotification notification) {
192 receivedNotification.set(notification);
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());
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());
206 assertFalse("Unexpected DOMEvent", actual instanceof org.opendaylight.mdsal.dom.api.DOMEvent);
209 receivedNotification = SettableFuture.create();
213 private static class TestLegacyDOMNotificationSubscriptionListener implements DOMNotificationSubscriptionListener {
214 SettableFuture<Set<SchemaPath>> receivedNotification = SettableFuture.create();
217 public void onSubscriptionChanged(final Set<SchemaPath> currentTypes) {
218 receivedNotification.set(currentTypes);
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();
228 void verifyNotReceived() {
229 Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
230 assertFalse("Unexpected notification", receivedNotification.isDone());
234 private static class TestLegacyDOMNotification implements DOMNotification {
236 public SchemaPath getType() {
237 return notificationSchemaPath;
241 public ContainerNode getBody() {
246 private static class TestLegacyDOMEvent extends TestLegacyDOMNotification implements DOMEvent {
248 public Date getEventTime() {
249 return Date.from(INSTANT);
253 private static class TestMdsalDOMNotification implements org.opendaylight.mdsal.dom.api.DOMNotification {
255 public SchemaPath getType() {
256 return notificationSchemaPath;
260 public ContainerNode getBody() {
265 private static class TestMdsalDOMEvent extends TestMdsalDOMNotification
266 implements org.opendaylight.mdsal.dom.api.DOMEvent {
268 public Instant getEventInstant() {