2 * Copyright (c) 2015 Brocade Communications Systems, Inc. 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.cluster.datastore;
10 import static org.junit.Assert.assertEquals;
11 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.INNER_LIST_QNAME;
12 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.OUTER_CONTAINER_PATH;
13 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.OUTER_CONTAINER_QNAME;
14 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.OUTER_LIST_PATH;
15 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.OUTER_LIST_QNAME;
16 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.TEST_PATH;
17 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.TEST_QNAME;
18 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.innerEntryPath;
19 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.innerNode;
20 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerEntryKey;
21 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerEntryPath;
22 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerNode;
23 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerNodeEntry;
24 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.testNodeWithOuter;
26 import akka.actor.ActorRef;
27 import akka.testkit.TestActorRef;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
32 import org.opendaylight.controller.cluster.datastore.utils.MockDataChangeListener;
33 import org.opendaylight.controller.cluster.raft.TestActorFactory;
34 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
37 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
40 * Unit tests for DataChangeListenerSupport.
42 * @author Thomas Pantelis
44 public class DataChangeListenerSupportTest extends AbstractShardTest {
45 private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
48 private DataChangeListenerSupport support;
51 public void setup() throws InterruptedException {
52 shard = createShard();
53 support = new DataChangeListenerSupport(shard);
58 public void tearDown() {
64 public void testChangeListenerWithNoInitialData() throws Exception {
65 MockDataChangeListener listener = registerChangeListener(TEST_PATH, DataChangeScope.ONE, 0, true);
67 listener.expectNoMoreChanges("Unexpected initial change event");
71 public void testInitialChangeListenerEventWithContainerPath() throws Exception {
72 writeToStore(shard.getDataStore(), TEST_PATH, ImmutableNodes.containerNode(TEST_QNAME));
74 MockDataChangeListener listener = registerChangeListener(TEST_PATH, DataChangeScope.ONE, 1, true);
76 listener.waitForChangeEvents(TEST_PATH);
80 public void testInitialChangeListenerEventWithListPath() throws Exception {
81 mergeToStore(shard.getDataStore(), TEST_PATH, testNodeWithOuter(1, 2));
83 MockDataChangeListener listener = registerChangeListener(OUTER_LIST_PATH, DataChangeScope.ONE, 1, true);
85 listener.waitForChangeEvents();
86 assertEquals("Outer entry 1 present", true, NormalizedNodes.findNode(
87 listener.getCreatedData(0, OUTER_LIST_PATH), outerEntryKey(1)).isPresent());
88 assertEquals("Outer entry 2 present", true, NormalizedNodes.findNode(
89 listener.getCreatedData(0, OUTER_LIST_PATH), outerEntryKey(2)).isPresent());
93 public void testInitialChangeListenerEventWithWildcardedListPath() throws Exception {
94 mergeToStore(shard.getDataStore(), TEST_PATH, testNodeWithOuter(1, 2));
95 writeToStore(shard.getDataStore(), OUTER_CONTAINER_PATH, ImmutableNodes.containerNode(OUTER_CONTAINER_QNAME));
97 MockDataChangeListener listener = registerChangeListener(OUTER_LIST_PATH.node(OUTER_LIST_QNAME),
98 DataChangeScope.ONE, 1, true);
100 listener.waitForChangeEvents();
101 listener.verifyCreatedData(0, outerEntryPath(1));
102 listener.verifyCreatedData(0, outerEntryPath(2));
103 listener.verifyNoCreatedData(0, OUTER_CONTAINER_PATH);
107 public void testInitialChangeListenerEventWithNestedWildcardedListsPath() throws Exception {
108 mergeToStore(shard.getDataStore(), TEST_PATH, testNodeWithOuter(outerNode(
109 outerNodeEntry(1, innerNode("one", "two")), outerNodeEntry(2, innerNode("three", "four")))));
111 MockDataChangeListener listener = registerChangeListener(
112 OUTER_LIST_PATH.node(OUTER_LIST_QNAME).node(INNER_LIST_QNAME).node(INNER_LIST_QNAME),
113 DataChangeScope.ONE, 1, true);
115 listener.waitForChangeEvents();
116 listener.verifyCreatedData(0, innerEntryPath(1, "one"));
117 listener.verifyCreatedData(0, innerEntryPath(1, "two"));
118 listener.verifyCreatedData(0, innerEntryPath(2, "three"));
119 listener.verifyCreatedData(0, innerEntryPath(2, "four"));
121 // Register for a specific outer list entry
123 MockDataChangeListener listener2 = registerChangeListener(
124 OUTER_LIST_PATH.node(outerEntryKey(1)).node(INNER_LIST_QNAME).node(INNER_LIST_QNAME),
125 DataChangeScope.ONE, 1, true);
127 listener2.waitForChangeEvents();
128 listener2.verifyCreatedData(0, innerEntryPath(1, "one"));
129 listener2.verifyCreatedData(0, innerEntryPath(1, "two"));
130 listener2.verifyNoCreatedData(0, innerEntryPath(2, "three"));
131 listener2.verifyNoCreatedData(0, innerEntryPath(2, "four"));
135 public void testInitialChangeListenerEventWhenNotInitiallyLeader() throws Exception {
136 mergeToStore(shard.getDataStore(), TEST_PATH, testNodeWithOuter(outerNode(
137 outerNodeEntry(1, innerNode("one", "two")), outerNodeEntry(2, innerNode("three", "four")))));
139 MockDataChangeListener listener = registerChangeListener(
140 OUTER_LIST_PATH.node(OUTER_LIST_QNAME).node(INNER_LIST_QNAME).node(INNER_LIST_QNAME),
141 DataChangeScope.ONE, 0, false);
143 listener.expectNoMoreChanges("Unexpected initial change event");
146 support.onLeadershipChange(true, true);
148 listener.waitForChangeEvents();
149 listener.verifyCreatedData(0, innerEntryPath(1, "one"));
150 listener.verifyCreatedData(0, innerEntryPath(1, "two"));
151 listener.verifyCreatedData(0, innerEntryPath(2, "three"));
152 listener.verifyCreatedData(0, innerEntryPath(2, "four"));
155 private MockDataChangeListener registerChangeListener(final YangInstanceIdentifier path, final DataChangeScope scope,
156 final int expectedEvents, final boolean isLeader) {
157 MockDataChangeListener listener = new MockDataChangeListener(expectedEvents);
158 ActorRef dclActor = actorFactory.createActor(DataChangeListener.props(listener, path));
160 support.onMessage(new RegisterChangeListener(path, dclActor, scope, false), isLeader, true);
164 private Shard createShard() {
165 TestActorRef<Shard> actor = actorFactory.createTestActor(newShardProps());
166 return actor.underlyingActor();