blob: 7a4139511022e7e8f00d35b58cddade6cb3b30b6 [file] [log] [blame]
Madan Jampani79924fa2016-09-13 13:57:03 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Madan Jampani79924fa2016-09-13 13:57:03 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.store.primitives.resources.impl;
18
Sithara Punnasseryc3658c72017-08-07 11:16:08 -070019import java.util.Arrays;
Jordan Haltermand0d80352017-08-10 15:08:27 -070020import java.util.Iterator;
Sithara Punnasseryc3658c72017-08-07 11:16:08 -070021import java.util.List;
Madan Jampani79924fa2016-09-13 13:57:03 -070022import java.util.Map;
23import java.util.UUID;
24import java.util.concurrent.ArrayBlockingQueue;
25import java.util.concurrent.BlockingQueue;
26
Jordan Halterman2bf177c2017-06-29 01:49:08 -070027import com.google.common.base.Throwables;
28import io.atomix.protocols.raft.proxy.RaftProxy;
29import io.atomix.protocols.raft.service.RaftService;
Yuta HIGUCHI1edc36b2018-01-24 23:39:06 -080030
Madan Jampani79924fa2016-09-13 13:57:03 -070031import org.junit.Test;
Sithara Punnasseryc3658c72017-08-07 11:16:08 -070032import org.onosproject.store.primitives.NodeUpdate;
33import org.onosproject.store.primitives.TransactionId;
Madan Jampani79924fa2016-09-13 13:57:03 -070034import org.onosproject.store.service.DocumentPath;
35import org.onosproject.store.service.DocumentTreeEvent;
36import org.onosproject.store.service.DocumentTreeListener;
37import org.onosproject.store.service.IllegalDocumentModificationException;
38import org.onosproject.store.service.NoSuchDocumentPathException;
Jordan Haltermand0d80352017-08-10 15:08:27 -070039import org.onosproject.store.service.Ordering;
Sithara Punnasseryc3658c72017-08-07 11:16:08 -070040import org.onosproject.store.service.TransactionLog;
41import org.onosproject.store.service.Version;
Madan Jampani79924fa2016-09-13 13:57:03 -070042import org.onosproject.store.service.Versioned;
43
Jordan Halterman2bf177c2017-06-29 01:49:08 -070044import static org.junit.Assert.assertArrayEquals;
45import static org.junit.Assert.assertEquals;
46import static org.junit.Assert.assertFalse;
47import static org.junit.Assert.assertNull;
48import static org.junit.Assert.assertTrue;
49import static org.junit.Assert.fail;
Madan Jampani79924fa2016-09-13 13:57:03 -070050
51/**
52 * Unit tests for {@link AtomixDocumentTree}.
53 */
Jordan Halterman2bf177c2017-06-29 01:49:08 -070054public class AtomixDocumentTreeTest extends AtomixTestBase<AtomixDocumentTree> {
Jordan Haltermand0d80352017-08-10 15:08:27 -070055 private Ordering ordering = Ordering.NATURAL;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070056
57 @Override
58 protected RaftService createService() {
Jordan Haltermand0d80352017-08-10 15:08:27 -070059 return new AtomixDocumentTreeService(ordering);
Madan Jampani79924fa2016-09-13 13:57:03 -070060 }
61
Madan Jampani79924fa2016-09-13 13:57:03 -070062 @Override
Jordan Halterman2bf177c2017-06-29 01:49:08 -070063 protected AtomixDocumentTree createPrimitive(RaftProxy proxy) {
64 return new AtomixDocumentTree(proxy);
Madan Jampani79924fa2016-09-13 13:57:03 -070065 }
Jordan Halterman2bf177c2017-06-29 01:49:08 -070066
Jordan Haltermand0d80352017-08-10 15:08:27 -070067 @Override
68 protected AtomixDocumentTree newPrimitive(String name) {
69 return newPrimitive(name, Ordering.NATURAL);
70 }
71
72 protected AtomixDocumentTree newPrimitive(String name, Ordering ordering) {
73 this.ordering = ordering;
74 return super.newPrimitive(name);
75 }
76
Madan Jampani79924fa2016-09-13 13:57:03 -070077 /**
78 * Tests queries (get and getChildren).
79 */
80 @Test
81 public void testQueries() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -070082 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -070083 Versioned<byte[]> root = tree.get(path("root")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -070084 assertEquals(1, root.version());
85 assertNull(root.value());
86 }
87
88 /**
89 * Tests create.
90 */
91 @Test
92 public void testCreate() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -070093 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -070094 tree.create(path("root.a"), "a".getBytes()).join();
95 tree.create(path("root.a.b"), "ab".getBytes()).join();
96 tree.create(path("root.a.c"), "ac".getBytes()).join();
97 Versioned<byte[]> a = tree.get(path("root.a")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -070098 assertArrayEquals("a".getBytes(), a.value());
99
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700100 Versioned<byte[]> ab = tree.get(path("root.a.b")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700101 assertArrayEquals("ab".getBytes(), ab.value());
102
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700103 Versioned<byte[]> ac = tree.get(path("root.a.c")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700104 assertArrayEquals("ac".getBytes(), ac.value());
Madan Jampani4c8e3fe2016-09-16 16:20:28 -0700105
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700106 tree.create(path("root.x"), null).join();
107 Versioned<byte[]> x = tree.get(path("root.x")).join();
Madan Jampani4c8e3fe2016-09-16 16:20:28 -0700108 assertNull(x.value());
Madan Jampani79924fa2016-09-13 13:57:03 -0700109 }
110
111 /**
Madan Jampani86983282016-09-15 14:55:48 -0700112 * Tests recursive create.
113 */
114 @Test
115 public void testRecursiveCreate() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700116 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700117 tree.createRecursive(path("root.a.b.c"), "abc".getBytes()).join();
118 Versioned<byte[]> a = tree.get(path("root.a")).join();
Madan Jampani4c8e3fe2016-09-16 16:20:28 -0700119 assertArrayEquals(null, a.value());
Madan Jampani86983282016-09-15 14:55:48 -0700120
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700121 Versioned<byte[]> ab = tree.get(path("root.a.b")).join();
Madan Jampani4c8e3fe2016-09-16 16:20:28 -0700122 assertArrayEquals(null, ab.value());
Madan Jampani86983282016-09-15 14:55:48 -0700123
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700124 Versioned<byte[]> abc = tree.get(path("root.a.b.c")).join();
Madan Jampani86983282016-09-15 14:55:48 -0700125 assertArrayEquals("abc".getBytes(), abc.value());
126 }
127
128 /**
Jordan Haltermand0d80352017-08-10 15:08:27 -0700129 * Tests child node order.
130 */
131 @Test
132 public void testOrder() throws Throwable {
133 AtomixDocumentTree naturalTree = newPrimitive(UUID.randomUUID().toString(), Ordering.NATURAL);
134 naturalTree.create(path("root.c"), "foo".getBytes());
135 naturalTree.create(path("root.b"), "bar".getBytes());
136 naturalTree.create(path("root.a"), "baz".getBytes());
137
138 Iterator<Map.Entry<String, Versioned<byte[]>>> naturalIterator = naturalTree.getChildren(path("root"))
139 .join().entrySet().iterator();
140 assertEquals("a", naturalIterator.next().getKey());
141 assertEquals("b", naturalIterator.next().getKey());
142 assertEquals("c", naturalIterator.next().getKey());
143
144 AtomixDocumentTree insertionTree = newPrimitive(UUID.randomUUID().toString(), Ordering.INSERTION);
145 insertionTree.create(path("root.c"), "foo".getBytes());
146 insertionTree.create(path("root.b"), "bar".getBytes());
147 insertionTree.create(path("root.a"), "baz".getBytes());
148
149 Iterator<Map.Entry<String, Versioned<byte[]>>> insertionIterator = insertionTree.getChildren(path("root"))
150 .join().entrySet().iterator();
151 assertEquals("c", insertionIterator.next().getKey());
152 assertEquals("b", insertionIterator.next().getKey());
153 assertEquals("a", insertionIterator.next().getKey());
154 }
155
156 /**
Madan Jampani79924fa2016-09-13 13:57:03 -0700157 * Tests set.
158 */
159 @Test
160 public void testSet() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700161 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700162 tree.create(path("root.a"), "a".getBytes()).join();
163 tree.create(path("root.a.b"), "ab".getBytes()).join();
164 tree.create(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700165
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700166 tree.set(path("root.a.d"), "ad".getBytes()).join();
167 Versioned<byte[]> ad = tree.get(path("root.a.d")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700168 assertArrayEquals("ad".getBytes(), ad.value());
169
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700170 tree.set(path("root.a"), "newA".getBytes()).join();
171 Versioned<byte[]> newA = tree.get(path("root.a")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700172 assertArrayEquals("newA".getBytes(), newA.value());
173
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700174 tree.set(path("root.a.b"), "newAB".getBytes()).join();
175 Versioned<byte[]> newAB = tree.get(path("root.a.b")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700176 assertArrayEquals("newAB".getBytes(), newAB.value());
Madan Jampani4c8e3fe2016-09-16 16:20:28 -0700177
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700178 tree.set(path("root.x"), null).join();
179 Versioned<byte[]> x = tree.get(path("root.x")).join();
Madan Jampani4c8e3fe2016-09-16 16:20:28 -0700180 assertNull(x.value());
Madan Jampani79924fa2016-09-13 13:57:03 -0700181 }
182
183 /**
184 * Tests replace if version matches.
185 */
186 @Test
187 public void testReplaceVersion() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700188 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700189 tree.create(path("root.a"), "a".getBytes()).join();
190 tree.create(path("root.a.b"), "ab".getBytes()).join();
191 tree.create(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700192
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700193 Versioned<byte[]> ab = tree.get(path("root.a.b")).join();
194 assertTrue(tree.replace(path("root.a.b"), "newAB".getBytes(), ab.version()).join());
195 Versioned<byte[]> newAB = tree.get(path("root.a.b")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700196 assertArrayEquals("newAB".getBytes(), newAB.value());
197
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700198 assertFalse(tree.replace(path("root.a.b"), "newestAB".getBytes(), ab.version()).join());
199 assertArrayEquals("newAB".getBytes(), tree.get(path("root.a.b")).join().value());
Madan Jampani79924fa2016-09-13 13:57:03 -0700200
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700201 assertFalse(tree.replace(path("root.a.d"), "foo".getBytes(), 1).join());
Madan Jampani79924fa2016-09-13 13:57:03 -0700202 }
203
204 /**
205 * Tests replace if value matches.
206 */
207 @Test
208 public void testReplaceValue() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700209 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700210 tree.create(path("root.a"), "a".getBytes()).join();
211 tree.create(path("root.a.b"), "ab".getBytes()).join();
212 tree.create(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700213
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700214 Versioned<byte[]> ab = tree.get(path("root.a.b")).join();
215 assertTrue(tree.replace(path("root.a.b"), "newAB".getBytes(), ab.value()).join());
216 Versioned<byte[]> newAB = tree.get(path("root.a.b")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700217 assertArrayEquals("newAB".getBytes(), newAB.value());
218
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700219 assertFalse(tree.replace(path("root.a.b"), "newestAB".getBytes(), ab.value()).join());
220 assertArrayEquals("newAB".getBytes(), tree.get(path("root.a.b")).join().value());
Madan Jampani79924fa2016-09-13 13:57:03 -0700221
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700222 assertFalse(tree.replace(path("root.a.d"), "bar".getBytes(), "foo".getBytes()).join());
Yuta HIGUCHI1edc36b2018-01-24 23:39:06 -0800223
224 assertTrue(tree.replace(path("root.x"), "beta".getBytes(), null).join());
225
Madan Jampani79924fa2016-09-13 13:57:03 -0700226 }
227
228 /**
229 * Tests remove.
230 */
231 @Test
232 public void testRemove() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700233 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700234 tree.create(path("root.a"), "a".getBytes()).join();
235 tree.create(path("root.a.b"), "ab".getBytes()).join();
236 tree.create(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700237
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700238 Versioned<byte[]> ab = tree.removeNode(path("root.a.b")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700239 assertArrayEquals("ab".getBytes(), ab.value());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700240 assertNull(tree.get(path("root.a.b")).join());
Madan Jampani79924fa2016-09-13 13:57:03 -0700241
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700242 Versioned<byte[]> ac = tree.removeNode(path("root.a.c")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700243 assertArrayEquals("ac".getBytes(), ac.value());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700244 assertNull(tree.get(path("root.a.c")).join());
Madan Jampani79924fa2016-09-13 13:57:03 -0700245
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700246 Versioned<byte[]> a = tree.removeNode(path("root.a")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700247 assertArrayEquals("a".getBytes(), a.value());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700248 assertNull(tree.get(path("root.a")).join());
Madan Jampani4c8e3fe2016-09-16 16:20:28 -0700249
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700250 tree.create(path("root.x"), null).join();
251 Versioned<byte[]> x = tree.removeNode(path("root.x")).join();
Madan Jampani4c8e3fe2016-09-16 16:20:28 -0700252 assertNull(x.value());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700253 assertNull(tree.get(path("root.a.x")).join());
Madan Jampani79924fa2016-09-13 13:57:03 -0700254 }
255
256 /**
257 * Tests invalid removes.
258 */
259 @Test
260 public void testRemoveFailures() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700261 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700262 tree.create(path("root.a"), "a".getBytes()).join();
263 tree.create(path("root.a.b"), "ab".getBytes()).join();
264 tree.create(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700265
266 try {
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700267 tree.removeNode(path("root")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700268 fail();
269 } catch (Exception e) {
270 assertTrue(Throwables.getRootCause(e) instanceof IllegalDocumentModificationException);
271 }
272
273 try {
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700274 tree.removeNode(path("root.a")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700275 fail();
276 } catch (Exception e) {
277 assertTrue(Throwables.getRootCause(e) instanceof IllegalDocumentModificationException);
278 }
279
280 try {
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700281 tree.removeNode(path("root.d")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700282 fail();
283 } catch (Exception e) {
284 assertTrue(Throwables.getRootCause(e) instanceof NoSuchDocumentPathException);
285 }
286 }
287
288 /**
289 * Tests invalid create.
290 */
291 @Test
292 public void testCreateFailures() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700293 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Madan Jampani79924fa2016-09-13 13:57:03 -0700294 try {
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700295 tree.create(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700296 fail();
297 } catch (Exception e) {
298 assertTrue(Throwables.getRootCause(e) instanceof IllegalDocumentModificationException);
299 }
300 }
301
302 /**
303 * Tests invalid set.
304 */
305 @Test
306 public void testSetFailures() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700307 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Madan Jampani79924fa2016-09-13 13:57:03 -0700308 try {
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700309 tree.set(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700310 fail();
311 } catch (Exception e) {
312 assertTrue(Throwables.getRootCause(e) instanceof IllegalDocumentModificationException);
313 }
314 }
315
316 /**
317 * Tests getChildren.
318 */
319 @Test
320 public void testGetChildren() throws Throwable {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700321 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700322 tree.create(path("root.a"), "a".getBytes()).join();
323 tree.create(path("root.a.b"), "ab".getBytes()).join();
324 tree.create(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700325
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700326 Map<String, Versioned<byte[]>> rootChildren = tree.getChildren(path("root")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700327 assertEquals(1, rootChildren.size());
328 Versioned<byte[]> a = rootChildren.get("a");
329 assertArrayEquals("a".getBytes(), a.value());
330
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700331 Map<String, Versioned<byte[]>> children = tree.getChildren(path("root.a")).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700332 assertEquals(2, children.size());
333 Versioned<byte[]> ab = children.get("b");
334 assertArrayEquals("ab".getBytes(), ab.value());
335 Versioned<byte[]> ac = children.get("c");
336 assertArrayEquals("ac".getBytes(), ac.value());
337
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700338 assertEquals(0, tree.getChildren(path("root.a.b")).join().size());
339 assertEquals(0, tree.getChildren(path("root.a.c")).join().size());
Madan Jampani79924fa2016-09-13 13:57:03 -0700340 }
341
342 /**
343 * Tests destroy.
344 */
345 @Test
346 public void testClear() {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700347 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700348 tree.create(path("root.a"), "a".getBytes()).join();
349 tree.create(path("root.a.b"), "ab".getBytes()).join();
350 tree.create(path("root.a.c"), "ac".getBytes()).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700351
352 tree.destroy().join();
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700353 assertEquals(0, tree.getChildren(path("root")).join().size());
Madan Jampani79924fa2016-09-13 13:57:03 -0700354 }
355
356 /**
357 * Tests listeners.
358 */
359 @Test
Madan Jampani79924fa2016-09-13 13:57:03 -0700360 public void testNotifications() throws Exception {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700361 AtomixDocumentTree tree = newPrimitive(UUID.randomUUID().toString());
Madan Jampani79924fa2016-09-13 13:57:03 -0700362 TestEventListener listener = new TestEventListener();
363
364 // add listener; create a node in the tree and verify an CREATED event is received.
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700365 tree.addListener(listener).thenCompose(v -> tree.set(path("root.a"), "a".getBytes())).join();
Madan Jampani79924fa2016-09-13 13:57:03 -0700366 DocumentTreeEvent<byte[]> event = listener.event();
Madan Jampani79924fa2016-09-13 13:57:03 -0700367 assertEquals(DocumentTreeEvent.Type.CREATED, event.type());
Madan Jampanicdbf6772016-09-15 15:41:34 -0700368 assertFalse(event.oldValue().isPresent());
Madan Jampani79924fa2016-09-13 13:57:03 -0700369 assertArrayEquals("a".getBytes(), event.newValue().get().value());
Madan Jampanicdbf6772016-09-15 15:41:34 -0700370 // update a node in the tree and verify an UPDATED event is received.
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700371 tree.set(path("root.a"), "newA".getBytes()).join();
Madan Jampanicdbf6772016-09-15 15:41:34 -0700372 event = listener.event();
373 assertEquals(DocumentTreeEvent.Type.UPDATED, event.type());
374 assertArrayEquals("newA".getBytes(), event.newValue().get().value());
375 assertArrayEquals("a".getBytes(), event.oldValue().get().value());
376 // remove a node in the tree and verify an REMOVED event is received.
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700377 tree.removeNode(path("root.a")).join();
Madan Jampanicdbf6772016-09-15 15:41:34 -0700378 event = listener.event();
379 assertEquals(DocumentTreeEvent.Type.DELETED, event.type());
380 assertFalse(event.newValue().isPresent());
381 assertArrayEquals("newA".getBytes(), event.oldValue().get().value());
382 // recursively create a node and verify CREATED events for all intermediate nodes.
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700383 tree.createRecursive(path("root.x.y"), "xy".getBytes()).join();
Madan Jampanicdbf6772016-09-15 15:41:34 -0700384 event = listener.event();
385 assertEquals(DocumentTreeEvent.Type.CREATED, event.type());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700386 assertEquals(path("root.x"), event.path());
Madan Jampanicdbf6772016-09-15 15:41:34 -0700387 event = listener.event();
388 assertEquals(DocumentTreeEvent.Type.CREATED, event.type());
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700389 assertEquals(path("root.x.y"), event.path());
Madan Jampanicdbf6772016-09-15 15:41:34 -0700390 assertArrayEquals("xy".getBytes(), event.newValue().get().value());
Madan Jampani79924fa2016-09-13 13:57:03 -0700391 }
392
Madan Jampani98094222016-09-15 21:12:46 -0700393 @Test
394 public void testFilteredNotifications() throws Throwable {
Madan Jampani98094222016-09-15 21:12:46 -0700395 String treeName = UUID.randomUUID().toString();
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700396 AtomixDocumentTree tree1 = newPrimitive(treeName);
397 AtomixDocumentTree tree2 = newPrimitive(treeName);
Madan Jampani98094222016-09-15 21:12:46 -0700398
399 TestEventListener listener1a = new TestEventListener(3);
400 TestEventListener listener1ab = new TestEventListener(2);
401 TestEventListener listener2abc = new TestEventListener(1);
402
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700403 tree1.addListener(path("root.a"), listener1a).join();
404 tree1.addListener(path("root.a.b"), listener1ab).join();
405 tree2.addListener(path("root.a.b.c"), listener2abc).join();
Madan Jampani98094222016-09-15 21:12:46 -0700406
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700407 tree1.createRecursive(path("root.a.b.c"), "abc".getBytes()).join();
Madan Jampani98094222016-09-15 21:12:46 -0700408 DocumentTreeEvent<byte[]> event = listener1a.event();
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700409 assertEquals(path("root.a"), event.path());
Madan Jampani98094222016-09-15 21:12:46 -0700410 event = listener1a.event();
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700411 assertEquals(path("root.a.b"), event.path());
Madan Jampani98094222016-09-15 21:12:46 -0700412 event = listener1a.event();
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700413 assertEquals(path("root.a.b.c"), event.path());
Madan Jampani98094222016-09-15 21:12:46 -0700414 event = listener1ab.event();
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700415 assertEquals(path("root.a.b"), event.path());
Madan Jampani98094222016-09-15 21:12:46 -0700416 event = listener1ab.event();
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700417 assertEquals(path("root.a.b.c"), event.path());
Madan Jampani98094222016-09-15 21:12:46 -0700418 event = listener2abc.event();
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700419 assertEquals(path("root.a.b.c"), event.path());
Madan Jampani98094222016-09-15 21:12:46 -0700420 }
421
Sithara Punnasseryc3658c72017-08-07 11:16:08 -0700422 @Test
423 public void testTransaction() throws Throwable {
424 String treeName = UUID.randomUUID().toString();
425 AtomixDocumentTree tree = newPrimitive(treeName);
426
427 byte[] value1 = "abc".getBytes();
428 byte[] value2 = "def".getBytes();
429
430 assertTrue(tree.create(path("root.a"), value1).join());
431 assertTrue(tree.create(path("root.b"), value2).join());
432
433 long aVersion = tree.get(path("root.a")).join().version();
434 long bVersion = tree.get(path("root.b")).join().version();
435
436 TransactionId transactionId = TransactionId.from("1");
437 Version transactionVersion = tree.begin(transactionId).join();
438 List<NodeUpdate<byte[]>> records = Arrays.asList(
439 NodeUpdate.<byte[]>newBuilder()
440 .withType(NodeUpdate.Type.CREATE_NODE)
441 .withPath(path("root.c"))
442 .withValue(value1)
443 .build(),
444 NodeUpdate.<byte[]>newBuilder()
445 .withType(NodeUpdate.Type.UPDATE_NODE)
446 .withPath(path("root.a"))
447 .withValue(value2)
448 .withVersion(aVersion)
449 .build(),
450 NodeUpdate.<byte[]>newBuilder()
451 .withType(NodeUpdate.Type.DELETE_NODE)
452 .withPath(path("root.b"))
453 .withVersion(bVersion)
454 .build());
455 TransactionLog<NodeUpdate<byte[]>> transactionLog = new TransactionLog<>(
456 transactionId,
457 transactionVersion.value(),
458 records);
459 assertTrue(tree.prepare(transactionLog).join());
460 tree.commit(transactionId).join();
461
462 assertArrayEquals(value2, tree.get(path("root.a")).join().value());
463 assertNull(tree.get(path("root.b")).join());
464 assertArrayEquals(value1, tree.get(path("root.c")).join().value());
465 }
466
Madan Jampani79924fa2016-09-13 13:57:03 -0700467 private static class TestEventListener implements DocumentTreeListener<byte[]> {
468
Madan Jampani98094222016-09-15 21:12:46 -0700469 private final BlockingQueue<DocumentTreeEvent<byte[]>> queue;
470
471 public TestEventListener() {
472 this(1);
473 }
474
475 public TestEventListener(int maxEvents) {
476 queue = new ArrayBlockingQueue<>(maxEvents);
477 }
Madan Jampani79924fa2016-09-13 13:57:03 -0700478
479 @Override
480 public void event(DocumentTreeEvent<byte[]> event) {
Madan Jampani98094222016-09-15 21:12:46 -0700481
Madan Jampani79924fa2016-09-13 13:57:03 -0700482 try {
483 queue.put(event);
484 } catch (InterruptedException e) {
485 Throwables.propagate(e);
486 }
487 }
488
Madan Jampani79924fa2016-09-13 13:57:03 -0700489 public DocumentTreeEvent<byte[]> event() throws InterruptedException {
490 return queue.take();
491 }
492 }
Thomas Vachuskae2bd1152017-03-23 13:42:32 -0700493
494 private static DocumentPath path(String path) {
495 return DocumentPath.from(path.replace(".", DocumentPath.DEFAULT_SEPARATOR));
496 }
Madan Jampani79924fa2016-09-13 13:57:03 -0700497}