blob: dbaabd80c29f3218606da01a2ae534a5f56465b4 [file] [log] [blame]
Madan Jampani79924fa2016-09-13 13:57:03 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
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
19import static org.junit.Assert.assertArrayEquals;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertFalse;
22import static org.junit.Assert.assertNotNull;
23import static org.junit.Assert.assertNull;
24import static org.junit.Assert.assertTrue;
25import static org.junit.Assert.fail;
26import io.atomix.resource.ResourceType;
27
28import java.util.Map;
29import java.util.UUID;
30import java.util.concurrent.ArrayBlockingQueue;
31import java.util.concurrent.BlockingQueue;
32
33import org.junit.AfterClass;
34import org.junit.BeforeClass;
35import org.junit.Ignore;
36import org.junit.Test;
37import org.onosproject.store.service.DocumentPath;
38import org.onosproject.store.service.DocumentTreeEvent;
39import org.onosproject.store.service.DocumentTreeListener;
40import org.onosproject.store.service.IllegalDocumentModificationException;
41import org.onosproject.store.service.NoSuchDocumentPathException;
42import org.onosproject.store.service.Versioned;
43
44import com.google.common.base.Throwables;
45
46/**
47 * Unit tests for {@link AtomixDocumentTree}.
48 */
49public class AtomixDocumentTreeTest extends AtomixTestBase {
50 @BeforeClass
51 public static void preTestSetup() throws Throwable {
52 createCopycatServers(3);
53 }
54
55 @AfterClass
56 public static void postTestCleanup() throws Exception {
57 clearTests();
58 }
59 @Override
60 protected ResourceType resourceType() {
61 return new ResourceType(AtomixDocumentTree.class);
62 }
63 /**
64 * Tests queries (get and getChildren).
65 */
66 @Test
67 public void testQueries() throws Throwable {
68 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
69 AtomixDocumentTree.class).join();
70 Versioned<byte[]> root = tree.get(DocumentPath.from("root")).join();
71 assertEquals(1, root.version());
72 assertNull(root.value());
73 }
74
75 /**
76 * Tests create.
77 */
78 @Test
79 public void testCreate() throws Throwable {
80 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
81 AtomixDocumentTree.class).join();
82 tree.create(DocumentPath.from("root.a"), "a".getBytes()).join();
83 tree.create(DocumentPath.from("root.a.b"), "ab".getBytes()).join();
84 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
85 Versioned<byte[]> a = tree.get(DocumentPath.from("root.a")).join();
86 assertArrayEquals("a".getBytes(), a.value());
87
88 Versioned<byte[]> ab = tree.get(DocumentPath.from("root.a.b")).join();
89 assertArrayEquals("ab".getBytes(), ab.value());
90
91 Versioned<byte[]> ac = tree.get(DocumentPath.from("root.a.c")).join();
92 assertArrayEquals("ac".getBytes(), ac.value());
93 }
94
95 /**
Madan Jampani86983282016-09-15 14:55:48 -070096 * Tests recursive create.
97 */
98 @Test
99 public void testRecursiveCreate() throws Throwable {
100 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
101 AtomixDocumentTree.class).join();
102 tree.createRecursive(DocumentPath.from("root.a.b.c"), "abc".getBytes()).join();
103 Versioned<byte[]> a = tree.get(DocumentPath.from("root.a")).join();
104 assertArrayEquals(new byte[0], a.value());
105
106 Versioned<byte[]> ab = tree.get(DocumentPath.from("root.a.b")).join();
107 assertArrayEquals(new byte[0], ab.value());
108
109 Versioned<byte[]> abc = tree.get(DocumentPath.from("root.a.b.c")).join();
110 assertArrayEquals("abc".getBytes(), abc.value());
111 }
112
113 /**
Madan Jampani79924fa2016-09-13 13:57:03 -0700114 * Tests set.
115 */
116 @Test
117 public void testSet() throws Throwable {
118 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
119 AtomixDocumentTree.class).join();
120 tree.create(DocumentPath.from("root.a"), "a".getBytes()).join();
121 tree.create(DocumentPath.from("root.a.b"), "ab".getBytes()).join();
122 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
123
124 tree.set(DocumentPath.from("root.a.d"), "ad".getBytes()).join();
125 Versioned<byte[]> ad = tree.get(DocumentPath.from("root.a.d")).join();
126 assertArrayEquals("ad".getBytes(), ad.value());
127
128 tree.set(DocumentPath.from("root.a"), "newA".getBytes()).join();
129 Versioned<byte[]> newA = tree.get(DocumentPath.from("root.a")).join();
130 assertArrayEquals("newA".getBytes(), newA.value());
131
132 tree.set(DocumentPath.from("root.a.b"), "newAB".getBytes()).join();
133 Versioned<byte[]> newAB = tree.get(DocumentPath.from("root.a.b")).join();
134 assertArrayEquals("newAB".getBytes(), newAB.value());
135 }
136
137 /**
138 * Tests replace if version matches.
139 */
140 @Test
141 public void testReplaceVersion() throws Throwable {
142 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
143 AtomixDocumentTree.class).join();
144 tree.create(DocumentPath.from("root.a"), "a".getBytes()).join();
145 tree.create(DocumentPath.from("root.a.b"), "ab".getBytes()).join();
146 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
147
148 Versioned<byte[]> ab = tree.get(DocumentPath.from("root.a.b")).join();
149 assertTrue(tree.replace(DocumentPath.from("root.a.b"), "newAB".getBytes(), ab.version()).join());
150 Versioned<byte[]> newAB = tree.get(DocumentPath.from("root.a.b")).join();
151 assertArrayEquals("newAB".getBytes(), newAB.value());
152
153 assertFalse(tree.replace(DocumentPath.from("root.a.b"), "newestAB".getBytes(), ab.version()).join());
154 assertArrayEquals("newAB".getBytes(), tree.get(DocumentPath.from("root.a.b")).join().value());
155
156 assertFalse(tree.replace(DocumentPath.from("root.a.d"), "foo".getBytes(), 1).join());
157 }
158
159 /**
160 * Tests replace if value matches.
161 */
162 @Test
163 public void testReplaceValue() throws Throwable {
164 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
165 AtomixDocumentTree.class).join();
166 tree.create(DocumentPath.from("root.a"), "a".getBytes()).join();
167 tree.create(DocumentPath.from("root.a.b"), "ab".getBytes()).join();
168 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
169
170 Versioned<byte[]> ab = tree.get(DocumentPath.from("root.a.b")).join();
171 assertTrue(tree.replace(DocumentPath.from("root.a.b"), "newAB".getBytes(), ab.value()).join());
172 Versioned<byte[]> newAB = tree.get(DocumentPath.from("root.a.b")).join();
173 assertArrayEquals("newAB".getBytes(), newAB.value());
174
175 assertFalse(tree.replace(DocumentPath.from("root.a.b"), "newestAB".getBytes(), ab.value()).join());
176 assertArrayEquals("newAB".getBytes(), tree.get(DocumentPath.from("root.a.b")).join().value());
177
178 assertFalse(tree.replace(DocumentPath.from("root.a.d"), "bar".getBytes(), "foo".getBytes()).join());
179 }
180
181 /**
182 * Tests remove.
183 */
184 @Test
185 public void testRemove() throws Throwable {
186 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
187 AtomixDocumentTree.class).join();
188 tree.create(DocumentPath.from("root.a"), "a".getBytes()).join();
189 tree.create(DocumentPath.from("root.a.b"), "ab".getBytes()).join();
190 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
191
192 Versioned<byte[]> ab = tree.removeNode(DocumentPath.from("root.a.b")).join();
193 assertArrayEquals("ab".getBytes(), ab.value());
194 assertNull(tree.get(DocumentPath.from("root.a.b")).join());
195
196 Versioned<byte[]> ac = tree.removeNode(DocumentPath.from("root.a.c")).join();
197 assertArrayEquals("ac".getBytes(), ac.value());
198 assertNull(tree.get(DocumentPath.from("root.a.c")).join());
199
200 Versioned<byte[]> a = tree.removeNode(DocumentPath.from("root.a")).join();
201 assertArrayEquals("a".getBytes(), a.value());
202 assertNull(tree.get(DocumentPath.from("root.a")).join());
203 }
204
205 /**
206 * Tests invalid removes.
207 */
208 @Test
209 public void testRemoveFailures() throws Throwable {
210 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
211 AtomixDocumentTree.class).join();
212 tree.create(DocumentPath.from("root.a"), "a".getBytes()).join();
213 tree.create(DocumentPath.from("root.a.b"), "ab".getBytes()).join();
214 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
215
216 try {
217 tree.removeNode(DocumentPath.from("root")).join();
218 fail();
219 } catch (Exception e) {
220 assertTrue(Throwables.getRootCause(e) instanceof IllegalDocumentModificationException);
221 }
222
223 try {
224 tree.removeNode(DocumentPath.from("root.a")).join();
225 fail();
226 } catch (Exception e) {
227 assertTrue(Throwables.getRootCause(e) instanceof IllegalDocumentModificationException);
228 }
229
230 try {
231 tree.removeNode(DocumentPath.from("root.d")).join();
232 fail();
233 } catch (Exception e) {
234 assertTrue(Throwables.getRootCause(e) instanceof NoSuchDocumentPathException);
235 }
236 }
237
238 /**
239 * Tests invalid create.
240 */
241 @Test
242 public void testCreateFailures() throws Throwable {
243 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
244 AtomixDocumentTree.class).join();
245 try {
246 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
247 fail();
248 } catch (Exception e) {
249 assertTrue(Throwables.getRootCause(e) instanceof IllegalDocumentModificationException);
250 }
251 }
252
253 /**
254 * Tests invalid set.
255 */
256 @Test
257 public void testSetFailures() throws Throwable {
258 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
259 AtomixDocumentTree.class).join();
260 try {
261 tree.set(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
262 fail();
263 } catch (Exception e) {
264 assertTrue(Throwables.getRootCause(e) instanceof IllegalDocumentModificationException);
265 }
266 }
267
268 /**
269 * Tests getChildren.
270 */
271 @Test
272 public void testGetChildren() throws Throwable {
273 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
274 AtomixDocumentTree.class).join();
275 tree.create(DocumentPath.from("root.a"), "a".getBytes()).join();
276 tree.create(DocumentPath.from("root.a.b"), "ab".getBytes()).join();
277 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
278
279 Map<String, Versioned<byte[]>> rootChildren = tree.getChildren(DocumentPath.from("root")).join();
280 assertEquals(1, rootChildren.size());
281 Versioned<byte[]> a = rootChildren.get("a");
282 assertArrayEquals("a".getBytes(), a.value());
283
284 Map<String, Versioned<byte[]>> children = tree.getChildren(DocumentPath.from("root.a")).join();
285 assertEquals(2, children.size());
286 Versioned<byte[]> ab = children.get("b");
287 assertArrayEquals("ab".getBytes(), ab.value());
288 Versioned<byte[]> ac = children.get("c");
289 assertArrayEquals("ac".getBytes(), ac.value());
290
291 assertEquals(0, tree.getChildren(DocumentPath.from("root.a.b")).join().size());
292 assertEquals(0, tree.getChildren(DocumentPath.from("root.a.c")).join().size());
293 }
294
295 /**
296 * Tests destroy.
297 */
298 @Test
299 public void testClear() {
300 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
301 AtomixDocumentTree.class).join();
302 tree.create(DocumentPath.from("root.a"), "a".getBytes()).join();
303 tree.create(DocumentPath.from("root.a.b"), "ab".getBytes()).join();
304 tree.create(DocumentPath.from("root.a.c"), "ac".getBytes()).join();
305
306 tree.destroy().join();
307 assertEquals(0, tree.getChildren(DocumentPath.from("root")).join().size());
308 }
309
310 /**
311 * Tests listeners.
312 */
313 @Test
314 @Ignore
315 public void testNotifications() throws Exception {
316 AtomixDocumentTree tree = createAtomixClient().getResource(UUID.randomUUID().toString(),
317 AtomixDocumentTree.class).join();
318 TestEventListener listener = new TestEventListener();
319
320 // add listener; create a node in the tree and verify an CREATED event is received.
321 tree.addListener(listener).thenCompose(v -> tree.set(DocumentPath.from("root.a"), "a".getBytes())).join();
322 DocumentTreeEvent<byte[]> event = listener.event();
323 assertNotNull(event);
324 assertEquals(DocumentTreeEvent.Type.CREATED, event.type());
325 assertArrayEquals("a".getBytes(), event.newValue().get().value());
326 }
327
328 private static class TestEventListener implements DocumentTreeListener<byte[]> {
329
330 private final BlockingQueue<DocumentTreeEvent<byte[]>> queue = new ArrayBlockingQueue<>(1);
331
332 @Override
333 public void event(DocumentTreeEvent<byte[]> event) {
334 try {
335 queue.put(event);
336 } catch (InterruptedException e) {
337 Throwables.propagate(e);
338 }
339 }
340
Madan Jampani79924fa2016-09-13 13:57:03 -0700341 public DocumentTreeEvent<byte[]> event() throws InterruptedException {
342 return queue.take();
343 }
344 }
345}