blob: bc4db71ad4c21be341a4add8424d5e63ac999e19 [file] [log] [blame]
pierfa48c6e2019-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 allKeys.forEach(key -> {
98 switch (key) {
99 case KEY1:
100 assertThat(Lists.newArrayList(Versioned.valueOrNull(newMap.get(key))),
101 containsInAnyOrder(allValues.subList(0, 1).toArray()));
102 break;
103 case KEY2:
104 assertThat(Lists.newArrayList(Versioned.valueOrNull(newMap.get(key))),
105 containsInAnyOrder(allValues.subList(0, 2).toArray()));
106 break;
107 case KEY3:
108 assertThat(Lists.newArrayList(Versioned.valueOrNull(newMap.get(key))),
109 containsInAnyOrder(allValues.subList(0, 3).toArray()));
110 break;
111 default:
112 assertThat(Lists.newArrayList(Versioned.valueOrNull(newMap.get(key))),
113 containsInAnyOrder(allValues.subList(0, 4).toArray()));
114 break;
115 }
116 });
117 // Success
118 assertThat(newMap.removeAll(mapping), is(true));
119 // Failure
120 assertThat(newMap.removeAll(mapping), is(false));
121 // Verify operation
122 assertThat(newMap.size(), is(0));
123 assertThat(newMap.isEmpty(), is(true));
124 }
125
126 public static class AsyncConsistentMultimapMock<K, V> extends AsyncConsistentMultimapAdapter<K, V> {
127 private final Multimap<K, V> baseMap;
128 private static final int DEFAULT_CREATION_TIME = 0;
129 private static final int DEFAULT_VERSION = 0;
130
131 AsyncConsistentMultimapMock(Multimap<K, V> newBaseMap) {
132 baseMap = newBaseMap;
133 }
134
135 Versioned<Collection<? extends V>> makeVersioned(Collection<? extends V> v) {
136 return new Versioned<>(v, DEFAULT_VERSION, DEFAULT_CREATION_TIME);
137 }
138
139 @Override
140 public CompletableFuture<Integer> size() {
141 return CompletableFuture.completedFuture(baseMap.size());
142 }
143
144 @Override
145 public CompletableFuture<Boolean> isEmpty() {
146 return CompletableFuture.completedFuture(baseMap.isEmpty());
147 }
148
149 @Override
150 public CompletableFuture<Boolean> putAll(Map<K, Collection<? extends V>> mapping) {
151 CompletableFuture<Boolean> result = CompletableFuture.completedFuture(false);
152 for (Map.Entry<K, Collection<? extends V>> entry : mapping.entrySet()) {
153 if (baseMap.putAll(entry.getKey(), entry.getValue())) {
154 result = CompletableFuture.completedFuture(true);
155 }
156 }
157 return result;
158 }
159
160 @Override
161 public CompletableFuture<Versioned<Collection<? extends V>>> get(K key) {
162 return CompletableFuture.completedFuture(makeVersioned(baseMap.get(key)));
163 }
164
165 @Override
166 public CompletableFuture<Boolean> removeAll(Map<K, Collection<? extends V>> mapping) {
167 CompletableFuture<Boolean> result = CompletableFuture.completedFuture(false);
168 for (Map.Entry<K, Collection<? extends V>> entry : mapping.entrySet()) {
169 for (V value : entry.getValue()) {
170 if (baseMap.remove(entry.getKey(), value)) {
171 result = CompletableFuture.completedFuture(true);
172 }
173 }
174 }
175 return result;
176 }
177 }
178}