blob: 61a175aa380466d29bbd6d6d46909d20446f0cc3 [file] [log] [blame]
pier3edc0e92019-10-11 18:19:59 +02001/*
2 * Copyright 2019-present Open Networking Foundation
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;
18
19import com.google.common.collect.HashMultimap;
20import com.google.common.collect.Lists;
21import com.google.common.collect.Maps;
22import com.google.common.collect.Multimap;
23import org.junit.Test;
24import org.onosproject.store.service.AsyncConsistentMultimapAdapter;
25import org.onosproject.store.service.ConsistentMultimap;
26import org.onosproject.store.service.Versioned;
27
28import java.util.Collection;
29import java.util.List;
30import java.util.Map;
31import java.util.concurrent.CompletableFuture;
32
33import static org.hamcrest.MatcherAssert.assertThat;
34import static org.hamcrest.Matchers.containsInAnyOrder;
35import static org.hamcrest.Matchers.is;
36
37/**
38 * Tests for DefaultConsistentMultiMap.
39 */
40public class DefaultConsistentMultimapTest {
41
42 private static final String KEY1 = "AAA";
43 private static final String VALUE1 = "111";
44 private static final String KEY2 = "BBB";
45 private static final String VALUE2 = "222";
46 private static final String KEY3 = "CCC";
47 private static final String VALUE3 = "333";
48 private static final String KEY4 = "DDD";
49 private static final String VALUE4 = "444";
50 private final List<String> allKeys = Lists.newArrayList(KEY1, KEY2,
51 KEY3, KEY4);
52 private final List<String> allValues = Lists.newArrayList(VALUE1, VALUE2,
53 VALUE3, VALUE4);
54
55 /**
56 * Tests the behavior of public APIs of the default consistent multi-map
57 * implementation.
58 */
59 @Test
60 public void testBehavior() {
61 // Initialize the map
62 Multimap<String, String> baseMap = HashMultimap.create();
63 AsyncConsistentMultimapMock<String, String> asyncMultiMap = new AsyncConsistentMultimapMock<>(baseMap);
64 ConsistentMultimap<String, String> newMap = new DefaultConsistentMultimap<>(asyncMultiMap, 69);
65
66 // Verify is empty
67 assertThat(newMap.size(), is(0));
68 assertThat(newMap.isEmpty(), is(true));
69
70 // Test multi put
71 Map<String, Collection<? extends String>> mapping = Maps.newHashMap();
72 // First build the mappings having each key a different mapping
73 allKeys.forEach(key -> {
74 switch (key) {
75 case KEY1:
76 mapping.put(key, Lists.newArrayList(allValues.subList(0, 1)));
77 break;
78 case KEY2:
79 mapping.put(key, Lists.newArrayList(allValues.subList(0, 2)));
80 break;
81 case KEY3:
82 mapping.put(key, Lists.newArrayList(allValues.subList(0, 3)));
83 break;
84 default:
85 mapping.put(key, Lists.newArrayList(allValues.subList(0, 4)));
86 break;
87 }
88 });
89 // Success
90 assertThat(newMap.putAll(mapping), is(true));
91 // Failure
92 assertThat(newMap.putAll(mapping), is(false));
93 // Verify operation
94 assertThat(newMap.size(), is(10));
95 assertThat(newMap.isEmpty(), is(false));
96 // verify mapping is ok
97
98 allKeys.forEach(key -> {
99 List<String> actual = Lists.newArrayList(Versioned.valueOrNull(newMap.get(key)));
100 switch (key) {
101 case KEY1:
102 assertThat(actual, containsInAnyOrder(allValues.subList(0, 1).toArray()));
103 break;
104 case KEY2:
105 assertThat(actual, containsInAnyOrder(allValues.subList(0, 2).toArray()));
106 break;
107 case KEY3:
108 assertThat(actual, containsInAnyOrder(allValues.subList(0, 3).toArray()));
109 break;
110 default:
111 assertThat(actual, containsInAnyOrder(allValues.subList(0, 4).toArray()));
112 break;
113 }
114 });
115 // Success
116 assertThat(newMap.removeAll(mapping), is(true));
117 // Failure
118 assertThat(newMap.removeAll(mapping), is(false));
119 // Verify operation
120 assertThat(newMap.size(), is(0));
121 assertThat(newMap.isEmpty(), is(true));
122 }
123
124 public static class AsyncConsistentMultimapMock<K, V> extends AsyncConsistentMultimapAdapter<K, V> {
125 private final Multimap<K, V> baseMap;
126 private static final int DEFAULT_CREATION_TIME = 0;
127 private static final int DEFAULT_VERSION = 0;
128
129 AsyncConsistentMultimapMock(Multimap<K, V> newBaseMap) {
130 baseMap = newBaseMap;
131 }
132
133 Versioned<Collection<? extends V>> makeVersioned(Collection<? extends V> v) {
134 return new Versioned<>(v, DEFAULT_VERSION, DEFAULT_CREATION_TIME);
135 }
136
137 @Override
138 public CompletableFuture<Integer> size() {
139 return CompletableFuture.completedFuture(baseMap.size());
140 }
141
142 @Override
143 public CompletableFuture<Boolean> isEmpty() {
144 return CompletableFuture.completedFuture(baseMap.isEmpty());
145 }
146
147 @Override
148 public CompletableFuture<Boolean> putAll(Map<K, Collection<? extends V>> mapping) {
149 CompletableFuture<Boolean> result = CompletableFuture.completedFuture(false);
150 for (Map.Entry<K, Collection<? extends V>> entry : mapping.entrySet()) {
151 if (baseMap.putAll(entry.getKey(), entry.getValue())) {
152 result = CompletableFuture.completedFuture(true);
153 }
154 }
155 return result;
156 }
157
158 @Override
159 public CompletableFuture<Versioned<Collection<? extends V>>> get(K key) {
160 return CompletableFuture.completedFuture(makeVersioned(baseMap.get(key)));
161 }
162
163 @Override
164 public CompletableFuture<Boolean> removeAll(Map<K, Collection<? extends V>> mapping) {
165 CompletableFuture<Boolean> result = CompletableFuture.completedFuture(false);
166 for (Map.Entry<K, Collection<? extends V>> entry : mapping.entrySet()) {
167 for (V value : entry.getValue()) {
168 if (baseMap.remove(entry.getKey(), value)) {
169 result = CompletableFuture.completedFuture(true);
170 }
171 }
172 }
173 return result;
174 }
175 }
176}