BUG-2138: Create DistributedShardFrontend
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / DataChangeListenerSupportTest.java
1 /*
2  * Copyright (c) 2015 Brocade Communications Systems, Inc. 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.cluster.datastore;
9
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.innerEntryPath;
18 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.innerNode;
19 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerEntryKey;
20 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerEntryPath;
21 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerNode;
22 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerNodeEntry;
23 import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.testNodeWithOuter;
24
25 import akka.actor.ActorRef;
26 import akka.dispatch.Dispatchers;
27 import akka.testkit.TestActorRef;
28 import org.junit.Test;
29 import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
30 import org.opendaylight.controller.cluster.datastore.utils.MockDataChangeListener;
31 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
32 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
35 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
36
37 /**
38  * Unit tests for DataChangeListenerSupport.
39  *
40  * @author Thomas Pantelis
41  */
42 public class DataChangeListenerSupportTest extends AbstractShardTest {
43
44     @Test
45     public void testChangeListenerWithNoInitialData() throws Exception {
46
47         new ShardTestKit(getSystem()) {
48             {
49                 final TestActorRef<Shard> actor = actorFactory.createTestActor(
50                         newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()),
51                         "testChangeListenerWithNoInitialData");
52
53                 waitUntilLeader(actor);
54
55                 final Shard shard = actor.underlyingActor();
56                 final MockDataChangeListener listener = new MockDataChangeListener(0);
57                 final ActorRef dclActor = actorFactory.createActor(DataChangeListener.props(listener, TEST_PATH),
58                         "testChangeListenerWithNoInitialData-DataChangeListener");
59                 final DataChangeListenerSupport support = new DataChangeListenerSupport(shard);
60                 support.onMessage(new RegisterChangeListener(TEST_PATH, dclActor, DataChangeScope.ONE, false),
61                         true,true);
62
63                 listener.expectNoMoreChanges("Unexpected initial change event");
64             }
65         };
66     }
67
68     @Test
69     public void testInitialChangeListenerEventWithContainerPath() throws Exception {
70
71         new ShardTestKit(getSystem()) {
72             {
73                 final TestActorRef<Shard> actor = actorFactory.createTestActor(
74                         newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()),
75                         "testInitialChangeListenerEventWithContainerPath");
76
77                 waitUntilLeader(actor);
78
79                 final Shard shard = actor.underlyingActor();
80                 writeToStore(shard.getDataStore(), TestModel.TEST_PATH,
81                         ImmutableNodes.containerNode(TestModel.TEST_QNAME));
82                 final MockDataChangeListener listener = new MockDataChangeListener(1);
83                 final ActorRef dclActor = actorFactory.createActor(DataChangeListener.props(listener, TEST_PATH),
84                         "testInitialChangeListenerEventWithContainerPath-DataChangeListener");
85                 final DataChangeListenerSupport support = new DataChangeListenerSupport(shard);
86                 support.onMessage(new RegisterChangeListener(TEST_PATH, dclActor, DataChangeScope.ONE, false),
87                         true,true);
88
89                 listener.waitForChangeEvents(TEST_PATH);
90             }
91         };
92     }
93
94     @Test
95     public void testInitialChangeListenerEventWithListPath() throws Exception {
96         new ShardTestKit(getSystem()) {
97             {
98                 final TestActorRef<Shard> actor = actorFactory.createTestActor(
99                         newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()),
100                         "testInitialChangeListenerEventWithListPath");
101
102                 waitUntilLeader(actor);
103
104                 final Shard shard = actor.underlyingActor();
105                 mergeToStore(shard.getDataStore(), TEST_PATH, testNodeWithOuter(1, 2));
106
107                 final MockDataChangeListener listener = new MockDataChangeListener(1);
108                 final ActorRef dclActor = actorFactory.createActor(DataChangeListener.props(listener, OUTER_LIST_PATH),
109                         "testInitialChangeListenerEventWithListPath-DataChangeListener");
110                 final DataChangeListenerSupport support = new DataChangeListenerSupport(shard);
111                 support.onMessage(new RegisterChangeListener(OUTER_LIST_PATH, dclActor, DataChangeScope.ONE, false),
112                         true, true);
113
114                 listener.waitForChangeEvents();
115                 assertEquals("Outer entry 1 present", true, NormalizedNodes
116                         .findNode(listener.getCreatedData(0, OUTER_LIST_PATH), outerEntryKey(1)).isPresent());
117                 assertEquals("Outer entry 2 present", true, NormalizedNodes
118                         .findNode(listener.getCreatedData(0, OUTER_LIST_PATH), outerEntryKey(2)).isPresent());
119             }
120         };
121     }
122
123     @Test
124     public void testInitialChangeListenerEventWithWildcardedListPath() throws Exception {
125
126         new ShardTestKit(getSystem()) {
127             {
128                 final TestActorRef<Shard> actor = actorFactory.createTestActor(
129                         newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()),
130                         "testInitialChangeListenerEventWithWildcardedListPath");
131
132                 waitUntilLeader(actor);
133
134                 final Shard shard = actor.underlyingActor();
135
136                 mergeToStore(shard.getDataStore(), TEST_PATH, testNodeWithOuter(1, 2));
137                 writeToStore(shard.getDataStore(), OUTER_CONTAINER_PATH,
138                         ImmutableNodes.containerNode(OUTER_CONTAINER_QNAME));
139
140                 final MockDataChangeListener listener = new MockDataChangeListener(1);
141                 final YangInstanceIdentifier path = OUTER_LIST_PATH.node(OUTER_LIST_QNAME);
142                 final ActorRef dclActor = actorFactory.createActor(DataChangeListener.props(listener, path),
143                         "testInitialChangeListenerEventWithWildcardedListPath-DataChangeListener");
144                 final DataChangeListenerSupport support = new DataChangeListenerSupport(shard);
145                 support.onMessage(new RegisterChangeListener(path, dclActor, DataChangeScope.ONE, false), true, true);
146
147                 listener.waitForChangeEvents();
148                 listener.verifyCreatedData(0, outerEntryPath(1));
149                 listener.verifyCreatedData(0, outerEntryPath(2));
150                 listener.verifyNoCreatedData(0, OUTER_CONTAINER_PATH);
151             }
152         };
153     }
154
155     @Test
156     public void testInitialChangeListenerEventWithNestedWildcardedListsPath() throws Exception {
157
158         new ShardTestKit(getSystem()) {
159             {
160                 final TestActorRef<Shard> actor = actorFactory.createTestActor(
161                         newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()),
162                         "testInitialChangeListenerEventWithNestedWildcardedListsPath");
163
164                 waitUntilLeader(actor);
165
166                 final Shard shard = actor.underlyingActor();
167
168                 mergeToStore(shard.getDataStore(), TEST_PATH,
169                         testNodeWithOuter(outerNode(outerNodeEntry(1, innerNode("one", "two")),
170                                 outerNodeEntry(2, innerNode("three", "four")))));
171
172                 final MockDataChangeListener listener = new MockDataChangeListener(1);
173                 final YangInstanceIdentifier path = OUTER_LIST_PATH.node(OUTER_LIST_QNAME)
174                         .node(INNER_LIST_QNAME).node(INNER_LIST_QNAME);
175                 final ActorRef dclActor = actorFactory.createActor(DataChangeListener.props(listener, path),
176                         "testInitialChangeListenerEventWithNestedWildcardedListsPath-DataChangeListener");
177                 final DataChangeListenerSupport support = new DataChangeListenerSupport(shard);
178                 support.onMessage(new RegisterChangeListener(path, dclActor, DataChangeScope.ONE, false), true, true);
179
180
181                 listener.waitForChangeEvents();
182                 listener.verifyCreatedData(0, innerEntryPath(1, "one"));
183                 listener.verifyCreatedData(0, innerEntryPath(1, "two"));
184                 listener.verifyCreatedData(0, innerEntryPath(2, "three"));
185                 listener.verifyCreatedData(0, innerEntryPath(2, "four"));
186
187                 // Register for a specific outer list entry
188                 final MockDataChangeListener listener2 = new MockDataChangeListener(1);
189                 final YangInstanceIdentifier path2 = OUTER_LIST_PATH.node(outerEntryKey(1)).node(INNER_LIST_QNAME)
190                         .node(INNER_LIST_QNAME);
191                 final ActorRef dclActor2 = actorFactory.createActor(DataChangeListener.props(listener2, path2),
192                         "testInitialChangeListenerEventWithNestedWildcardedListsPath-DataChangeListener2");
193                 final DataChangeListenerSupport support2 = new DataChangeListenerSupport(shard);
194                 support2.onMessage(new RegisterChangeListener(path2, dclActor2, DataChangeScope.ONE, false),
195                         true, true);
196
197                 listener2.waitForChangeEvents();
198                 listener2.verifyCreatedData(0, innerEntryPath(1, "one"));
199                 listener2.verifyCreatedData(0, innerEntryPath(1, "two"));
200                 listener2.verifyNoCreatedData(0, innerEntryPath(2, "three"));
201                 listener2.verifyNoCreatedData(0, innerEntryPath(2, "four"));
202             }
203         };
204     }
205
206     @Test
207     public void testInitialChangeListenerEventWhenNotInitiallyLeader() throws Exception {
208
209         new ShardTestKit(getSystem()) {
210             {
211                 final TestActorRef<Shard> actor = actorFactory.createTestActor(
212                         newShardProps().withDispatcher(Dispatchers.DefaultDispatcherId()),
213                         "testInitialChangeListenerEventWhenNotInitiallyLeader");
214
215                 waitUntilLeader(actor);
216
217                 final Shard shard = actor.underlyingActor();
218
219                 mergeToStore(shard.getDataStore(), TEST_PATH,
220                         testNodeWithOuter(outerNode(outerNodeEntry(1, innerNode("one", "two")),
221                                 outerNodeEntry(2, innerNode("three", "four")))));
222
223                 final MockDataChangeListener listener = new MockDataChangeListener(0);
224                 final YangInstanceIdentifier path = OUTER_LIST_PATH.node(OUTER_LIST_QNAME).node(INNER_LIST_QNAME)
225                         .node(INNER_LIST_QNAME);
226                 final ActorRef dclActor = actorFactory.createActor(DataChangeListener.props(listener, path),
227                         "testInitialChangeListenerEventWhenNotInitiallyLeader-DataChangeListener");
228                 final DataChangeListenerSupport support = new DataChangeListenerSupport(shard);
229                 support.onMessage(new RegisterChangeListener(path, dclActor, DataChangeScope.ONE, false), false, true);
230
231                 listener.expectNoMoreChanges("Unexpected initial change event");
232                 listener.reset(1);
233
234                 support.onLeadershipChange(true, true);
235
236                 listener.waitForChangeEvents();
237                 listener.verifyCreatedData(0, innerEntryPath(1, "one"));
238                 listener.verifyCreatedData(0, innerEntryPath(1, "two"));
239                 listener.verifyCreatedData(0, innerEntryPath(2, "three"));
240                 listener.verifyCreatedData(0, innerEntryPath(2, "four"));
241             }
242         };
243     }
244 }