diff --git a/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapCompute.java b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapCompute.java new file mode 100644 index 0000000..0d1e24d --- /dev/null +++ b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapCompute.java @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2016 PANTHEON.tech, s.r.o. and others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tech.pantheon.triemap; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class TestConcurrentMapCompute { + private static final int COUNT = 50 * 1000; + + @Test + void testConcurrentMapCompute() { + final var map = TrieMap.create(); + + for (int i = 0; i < COUNT; i++) { + assertEquals(i + " -> null", map.compute(i, (k, v) -> k + " -> " + v)); + assertEquals(i + " -> " + i + " -> null", map.compute(i, (k, v) -> k + " -> " + v)); + } + } +} diff --git a/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapComputeIfAbsent.java b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapComputeIfAbsent.java new file mode 100644 index 0000000..11e9df1 --- /dev/null +++ b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapComputeIfAbsent.java @@ -0,0 +1,65 @@ +/* + * (C) Copyright 2016 PANTHEON.tech, s.r.o. and others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tech.pantheon.triemap; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertSame; + +class TestConcurrentMapComputeIfAbsent { + private static final int COUNT = 50 * 1000; + + @Test + void testConcurrentMapComputeIfAbsentReturnsComputedValue() { + final var map = TrieMap.create(); + for (int i = 0; i < COUNT; i++) { + assertEquals(Integer.toString(i), map.computeIfAbsent(i, Object::toString)); + } + } + + @Test + void testConcurrentMapComputeIfAbsentDoesNotComputeIfPresent() { + final var map = TrieMap.create(); + for (int i = 0; i < COUNT; i++) { + map.put(i, Integer.toString(i)); + assertEquals(Integer.toString(i), map.computeIfAbsent(i, + (ignored) -> fail("Should not have called function"))); + } + } + + @Test + void testConflictingHash() { + final var k1 = new ZeroHashInt(1); + final var k2 = new ZeroHashInt(2); + final var k3 = new ZeroHashInt(3); + final var k3dup = new ZeroHashInt(3); + final var v1 = new ZeroHashInt(4); + final var v2 = new ZeroHashInt(5); + final var v3 = new ZeroHashInt(6); + + final var map = TrieMap.create(); + // Pre-populate an LNode + assertSame(v1, map.computeIfAbsent(k1, k -> v1)); + assertSame(v2, map.computeIfAbsent(k2, k -> v2)); + assertSame(v3, map.computeIfAbsent(k3, k -> v3)); + + // Check with identical key + assertSame(v3, map.computeIfAbsent(k3, k -> v3)); + // Check with equivalent key + assertSame(v3, map.computeIfAbsent(k3dup, k -> v3)); + } +} \ No newline at end of file diff --git a/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapComputeIfPresent.java b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapComputeIfPresent.java new file mode 100644 index 0000000..0b3b971 --- /dev/null +++ b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapComputeIfPresent.java @@ -0,0 +1,80 @@ +/* + * (C) Copyright 2016 PANTHEON.tech, s.r.o. and others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tech.pantheon.triemap; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertSame; + +class TestConcurrentMapComputeIfPresent { + private static final int COUNT = 50 * 1000; + + @Test + void testConcurrentMapComputeIfPresentDoesNotComputeIfAbsent() { + final var map = TrieMap.create(); + + for (int i = 0; i < COUNT; i++) { + assertNull(map.computeIfPresent(i, (k, v) -> fail("Should not have called function"))); + assertFalse(map.containsKey(i)); + } + } + + + @Test + void testConcurrentMapComputeIfPresent() { + final var map = TrieMap.create(); + + for (int i = 0; i < COUNT; i++) { + map.put(i, "42"); + assertEquals(i + " -> 42", map.computeIfPresent(i, (k, v) -> k + " -> " + v)); + assertEquals(i + " -> 42", map.get(i)); + } + } + + @Test + void testConcurrentMapComputeIfPresentRemovesValueIfComputesNull() { + final var map = TrieMap.create(); + + for (int i = 0; i < COUNT; i++) { + map.put(i, "42"); + assertNull(map.computeIfPresent(i, (k, v) -> null)); + assertFalse(map.containsKey(i)); + } + } + + @Test + void testConflictingHash() { + final var k1 = new ZeroHashInt(1); + final var k2 = new ZeroHashInt(2); + final var k3 = new ZeroHashInt(3); + final var k3dup = new ZeroHashInt(3); + final var v1 = new ZeroHashInt(4); + final var v2 = new ZeroHashInt(5); + final var v3 = new ZeroHashInt(6); + + final var map = TrieMap.create(); + // Pre-populate an LNode + assertNull(map.putIfAbsent(k1, v1)); + assertNull(map.putIfAbsent(k2, v2)); + assertNull(map.putIfAbsent(k3, v3)); + + // Check with identical key + assertSame(v3, map.computeIfPresent(k3, (k, v) -> v3)); + // Check with equivalent key + assertSame(v3, map.computeIfPresent(k3dup, (k, v) -> v3)); + } +} diff --git a/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapMerge.java b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapMerge.java new file mode 100644 index 0000000..0b7e200 --- /dev/null +++ b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapMerge.java @@ -0,0 +1,46 @@ +/* + * (C) Copyright 2016 PANTHEON.tech, s.r.o. and others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tech.pantheon.triemap; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.Test; + +class TestConcurrentMapMerge { + private static final int COUNT = 50 * 1000; + + @Test + void testConcurrentMapMergeWhenValueAbsent() { + final var map = TrieMap.create(); + + for (int i = 0; i < COUNT; i++) { + final var newVal = Integer.toString(i + 10); + assertEquals(newVal, map.merge(i, newVal, (ov, nv) -> fail("Should not have been called"))); + } + } + + @Test + void testConcurrentMapMergeWhenValuePresent() { + final var map = TrieMap.create(); + + for (int i = 0; i < COUNT; i++) { + final var newVal = Integer.toString(i + 10); + map.put(i, newVal); + assertEquals(newVal + newVal, map.merge(i, newVal, (ov, nv) -> "" + ov + nv)); + } + } +} diff --git a/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapPutIfAbsent.java b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapPutIfAbsent.java index 99bb4ab..94be1db 100644 --- a/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapPutIfAbsent.java +++ b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapPutIfAbsent.java @@ -29,11 +29,22 @@ void testConcurrentMapPutIfAbsent() { final var map = TrieMap.create(); for (int i = 0; i < COUNT; i++) { - assertNull(map.putIfAbsent(i, i)); - assertEquals(Integer.valueOf(i), map.putIfAbsent(i, i)); + assertNull(map.putIfAbsent(i, i + 10)); + assertEquals(i + 10, map.get(i)); } } + @Test + void testConcurrentMapPutIfAbsentSkipsIfPresent() { + final var map = TrieMap.create(); + + for (int i = 0; i < COUNT; i++) { + map.put(i, i + 10); + assertEquals(i + 10, map.putIfAbsent(i, i + 20)); + } + } + + @Test void testConflictingHash() { final var k1 = new ZeroHashInt(1); diff --git a/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapReplace.java b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapReplace.java index ea7b62e..b728238 100644 --- a/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapReplace.java +++ b/triemap/src/test/java/tech/pantheon/triemap/TestConcurrentMapReplace.java @@ -33,7 +33,7 @@ void testConcurrentMapReplace() { assertNull(map.replace(i, "lol")); assertFalse(map.replace(i, i, "lol2")); assertNull(map.put(i, i)); - assertEquals(Integer.valueOf(i), map.replace(i, "lol")); + assertEquals(i, map.replace(i, "lol")); assertFalse(map.replace(i, i, "lol2")); assertTrue(map.replace(i, "lol", i)); }