diff options
author | 2022-12-14 00:57:24 +0100 | |
---|---|---|
committer | 2022-12-21 18:34:11 +0100 | |
commit | bfc9e33a54985797968708176690a9ecfc207f83 (patch) | |
tree | 600b4508eb1289c4e30a4f6e0aecfb9d5d56cefd /subprojects/store/src/test | |
parent | chore(deps): bump dependencies (diff) | |
download | refinery-bfc9e33a54985797968708176690a9ecfc207f83.tar.gz refinery-bfc9e33a54985797968708176690a9ecfc207f83.tar.zst refinery-bfc9e33a54985797968708176690a9ecfc207f83.zip |
refactor(store): compare VersionedMap instances
The Java hashCode and equals API is inappropriate here, because an
AnyVersionedMap is mutable. Added new methods to hash and compare
AnyVersionedMap instances by their contents and marked the built-in Java
methods as deprecated.
Diffstat (limited to 'subprojects/store/src/test')
2 files changed, 66 insertions, 56 deletions
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java index d7f77d1a..93ecfec3 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java | |||
@@ -17,12 +17,11 @@ import java.util.List; | |||
17 | import java.util.Random; | 17 | import java.util.Random; |
18 | import java.util.stream.Stream; | 18 | import java.util.stream.Stream; |
19 | 19 | ||
20 | import static org.junit.jupiter.api.Assertions.assertEquals; | 20 | import static org.junit.jupiter.api.Assertions.*; |
21 | import static org.junit.jupiter.api.Assertions.fail; | ||
22 | 21 | ||
23 | class ContentEqualsFuzzTest { | 22 | class ContentEqualsFuzzTest { |
24 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, | 23 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, |
25 | boolean evilHash) { | 24 | boolean evilHash) { |
26 | String[] values = MapTestEnvironment.prepareValues(maxValue); | 25 | String[] values = MapTestEnvironment.prepareValues(maxValue); |
27 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | 26 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); |
28 | 27 | ||
@@ -31,7 +30,9 @@ class ContentEqualsFuzzTest { | |||
31 | iterativeRandomPutsAndCommitsThenCompare(scenario, chp, steps, maxKey, values, r, commitFrequency); | 30 | iterativeRandomPutsAndCommitsThenCompare(scenario, chp, steps, maxKey, values, r, commitFrequency); |
32 | } | 31 | } |
33 | 32 | ||
34 | private void iterativeRandomPutsAndCommitsThenCompare(String scenario, ContinousHashProvider<Integer> chp, int steps, int maxKey, String[] values, Random r, int commitFrequency) { | 33 | private void iterativeRandomPutsAndCommitsThenCompare(String scenario, ContinousHashProvider<Integer> chp, |
34 | int steps, int maxKey, String[] values, Random r, | ||
35 | int commitFrequency) { | ||
35 | VersionedMapStore<Integer, String> store1 = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | 36 | VersionedMapStore<Integer, String> store1 = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); |
36 | VersionedMap<Integer, String> sut1 = store1.createMap(); | 37 | VersionedMap<Integer, String> sut1 = store1.createMap(); |
37 | 38 | ||
@@ -67,58 +68,43 @@ class ContentEqualsFuzzTest { | |||
67 | int index2 = 1; | 68 | int index2 = 1; |
68 | for (SimpleEntry<Integer, String> entry : content) { | 69 | for (SimpleEntry<Integer, String> entry : content) { |
69 | sut2.put(entry.getKey(), entry.getValue()); | 70 | sut2.put(entry.getKey(), entry.getValue()); |
70 | if(index2++%commitFrequency == 0) | 71 | if (index2++ % commitFrequency == 0) |
71 | sut2.commit(); | 72 | sut2.commit(); |
72 | } | 73 | } |
73 | 74 | ||
74 | // Check the integrity of the maps | 75 | // Check the integrity of the maps |
75 | ((VersionedMapImpl<Integer,String>) sut1).checkIntegrity(); | 76 | ((VersionedMapImpl<Integer, String>) sut1).checkIntegrity(); |
76 | ((VersionedMapImpl<Integer,String>) sut2).checkIntegrity(); | 77 | ((VersionedMapImpl<Integer, String>) sut2).checkIntegrity(); |
77 | 78 | ||
78 | // // Compare the two maps | 79 | // Compare the two maps |
79 | // By size | 80 | MapTestEnvironment.compareTwoMaps(scenario, sut1, sut2); |
80 | assertEquals(sut1.getSize(), content.size()); | ||
81 | assertEquals(sut2.getSize(), content.size()); | ||
82 | |||
83 | // By cursors | ||
84 | Cursor<Integer, String> cursor1 = sut1.getAll(); | ||
85 | Cursor<Integer, String> cursor2 = sut2.getAll(); | ||
86 | int index3 = 1; | ||
87 | boolean canMove = true; | ||
88 | do{ | ||
89 | boolean canMove1 = cursor1.move(); | ||
90 | boolean canMove2 = cursor2.move(); | ||
91 | assertEquals(canMove1, canMove2, scenario + ":" + index3 +" Cursors stopped at different times!"); | ||
92 | assertEquals(cursor1.getKey(), cursor2.getKey(), scenario + ":" + index3 +" Cursors have different keys!"); | ||
93 | assertEquals(cursor1.getValue(), cursor2.getValue(), scenario + ":" + index3 +" Cursors have different values!"); | ||
94 | |||
95 | canMove = canMove1; | ||
96 | MapTestEnvironment.printStatus(scenario, index3++, content.size(), "Compare"); | ||
97 | } while (canMove); | ||
98 | } | 81 | } |
99 | 82 | ||
100 | @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | 83 | @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} " + |
84 | "evil-hash={6}") | ||
101 | @MethodSource | 85 | @MethodSource |
102 | @Timeout(value = 10) | 86 | @Timeout(value = 10) |
103 | @Tag("fuzz") | 87 | @Tag("fuzz") |
104 | void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | 88 | void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, |
105 | boolean evilHash) { | 89 | boolean evilHash) { |
106 | runFuzzTest("CompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | 90 | runFuzzTest("CompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, |
107 | commitFrequency, evilHash); | 91 | commitFrequency, evilHash); |
108 | } | 92 | } |
109 | 93 | ||
110 | static Stream<Arguments> parametrizedFastFuzz() { | 94 | static Stream<Arguments> parametrizedFastFuzz() { |
111 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, | 95 | return FuzzTestUtils.permutationWithSize(new Object[]{FuzzTestUtils.FAST_STEP_COUNT}, new Object[]{3, 32, |
112 | new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, | 96 | 32 * 32}, |
113 | new Object[] { false, true }); | 97 | new Object[]{2, 3}, new Object[]{1, 10, 100}, new Object[]{1, 2, 3}, |
98 | new Object[]{false, true}); | ||
114 | } | 99 | } |
115 | 100 | ||
116 | @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | 101 | @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} " + |
102 | "evil-hash={6}") | ||
117 | @MethodSource | 103 | @MethodSource |
118 | @Tag("fuzz") | 104 | @Tag("fuzz") |
119 | @Tag("slow") | 105 | @Tag("slow") |
120 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | 106 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, |
121 | boolean evilHash) { | 107 | boolean evilHash) { |
122 | runFuzzTest("CompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | 108 | runFuzzTest("CompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, |
123 | commitFrequency, evilHash); | 109 | commitFrequency, evilHash); |
124 | } | 110 | } |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java index b73f8b32..2d03ebaf 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java | |||
@@ -1,8 +1,6 @@ | |||
1 | package tools.refinery.store.map.tests.utils; | 1 | package tools.refinery.store.map.tests.utils; |
2 | 2 | ||
3 | import tools.refinery.store.map.ContinousHashProvider; | 3 | import tools.refinery.store.map.*; |
4 | import tools.refinery.store.map.Cursor; | ||
5 | import tools.refinery.store.map.VersionedMap; | ||
6 | import tools.refinery.store.map.internal.VersionedMapImpl; | 4 | import tools.refinery.store.map.internal.VersionedMapImpl; |
7 | 5 | ||
8 | import java.util.*; | 6 | import java.util.*; |
@@ -50,40 +48,65 @@ public class MapTestEnvironment<K, V> { | |||
50 | 48 | ||
51 | } | 49 | } |
52 | 50 | ||
53 | public static <K, V> void compareTwoMaps(String title, VersionedMapImpl<K, V> map1, | 51 | public static <K, V> void compareTwoMaps(String title, VersionedMap<K, V> map1, |
54 | VersionedMapImpl<K, V> map2) { | 52 | VersionedMap<K, V> map2) { |
55 | compareTwoMaps(title, map1, map2, null); | 53 | compareTwoMaps(title, map1, map2, null); |
56 | } | 54 | } |
57 | public static <K, V> void compareTwoMaps(String title, VersionedMapImpl<K, V> map1, | 55 | |
58 | VersionedMapImpl<K, V> map2, List<Throwable> errors) { | 56 | public static <K, V> void compareTwoMaps(String title, VersionedMap<K, V> map1, |
57 | VersionedMap<K, V> map2, List<Throwable> errors) { | ||
58 | assertEqualsList(map1.getSize(), map2.getSize(), title + ": Sizes not equal", errors); | ||
59 | |||
59 | Cursor<K, V> cursor1 = map1.getAll(); | 60 | Cursor<K, V> cursor1 = map1.getAll(); |
60 | Cursor<K, V> cursor2 = map2.getAll(); | 61 | Cursor<K, V> cursor2 = map2.getAll(); |
61 | while (!cursor1.isTerminated()) { | 62 | while (!cursor1.isTerminated()) { |
62 | if (cursor2.isTerminated()) { | 63 | if (cursor2.isTerminated()) { |
63 | fail("cursor 2 terminated before cursor1"); | 64 | fail("cursor 2 terminated before cursor1"); |
64 | } | 65 | } |
65 | assertEqualsList(cursor1.getKey(), cursor2.getKey(),"Keys not equal", errors); | 66 | assertEqualsList(cursor1.getKey(), cursor2.getKey(), title + ": Keys not equal", errors); |
66 | assertEqualsList(cursor2.getValue(), cursor2.getValue(), "Values not equal", errors); | 67 | assertEqualsList(cursor2.getValue(), cursor2.getValue(), title + ": Values not equal", errors); |
67 | cursor1.move(); | 68 | cursor1.move(); |
68 | cursor2.move(); | 69 | cursor2.move(); |
69 | } | 70 | } |
70 | if (!cursor2.isTerminated()) | 71 | if (!cursor2.isTerminated()) { |
71 | fail("cursor 1 terminated before cursor 2"); | 72 | fail("cursor 1 terminated before cursor 2"); |
73 | } | ||
74 | |||
75 | for (var mode : ContentHashCode.values()) { | ||
76 | assertEqualsList(map1.contentHashCode(mode), map2.contentHashCode(mode), | ||
77 | title + ": " + mode + " hashCode check", errors); | ||
78 | } | ||
79 | assertContentEqualsList(map1, map2, title + ": map1.contentEquals(map2)", errors); | ||
80 | assertContentEqualsList(map2, map1, title + ": map2.contentEquals(map1)", errors); | ||
72 | } | 81 | } |
73 | 82 | ||
74 | private static void assertEqualsList(Object o1, Object o2, String message, List<Throwable> errors) { | 83 | private static void assertEqualsList(Object o1, Object o2, String message, List<Throwable> errors) { |
75 | if(errors == null) { | 84 | if (errors == null) { |
76 | assertEquals(o1, o2, message); | 85 | assertEquals(o1, o2, message); |
77 | } else { | 86 | } else { |
78 | if(o1 != null) { | 87 | if (o1 != null) { |
79 | if(!(o1.equals(o2))) { | 88 | if (!(o1.equals(o2))) { |
80 | AssertionError error = new AssertionError((message != null ? message+" " : "") + "expected: " + o1 + " but was : " + o2); | 89 | AssertionError error = |
90 | new AssertionError((message != null ? message + " " : "") + "expected: " + o1 + " but was " + | ||
91 | ": " + o2); | ||
81 | errors.add(error); | 92 | errors.add(error); |
82 | } | 93 | } |
83 | } | 94 | } |
84 | } | 95 | } |
85 | } | 96 | } |
86 | 97 | ||
98 | private static void assertContentEqualsList(AnyVersionedMap o1, AnyVersionedMap o2, String message, | ||
99 | List<Throwable> errors) { | ||
100 | boolean result = o1.contentEquals(o2); | ||
101 | if (errors == null) { | ||
102 | assertTrue(result, message); | ||
103 | } else if (!result) { | ||
104 | AssertionError error = | ||
105 | new AssertionError((message != null ? message + " " : "") + "expected: true but was: false"); | ||
106 | errors.add(error); | ||
107 | } | ||
108 | } | ||
109 | |||
87 | public VersionedMapImpl<K, V> sut; | 110 | public VersionedMapImpl<K, V> sut; |
88 | Map<K, V> oracle = new HashMap<K, V>(); | 111 | Map<K, V> oracle = new HashMap<K, V>(); |
89 | 112 | ||
@@ -99,10 +122,10 @@ public class MapTestEnvironment<K, V> { | |||
99 | } else { | 122 | } else { |
100 | oldOracleValue = oracle.remove(key); | 123 | oldOracleValue = oracle.remove(key); |
101 | } | 124 | } |
102 | if(oldSutValue == sut.getDefaultValue() && oldOracleValue != null) { | 125 | if (oldSutValue == sut.getDefaultValue() && oldOracleValue != null) { |
103 | fail("After put, SUT old nodeId was default, but oracle old value was " + oldOracleValue); | 126 | fail("After put, SUT old nodeId was default, but oracle old value was " + oldOracleValue); |
104 | } | 127 | } |
105 | if(oldSutValue != sut.getDefaultValue()) { | 128 | if (oldSutValue != sut.getDefaultValue()) { |
106 | assertEquals(oldOracleValue, oldSutValue); | 129 | assertEquals(oldOracleValue, oldSutValue); |
107 | } | 130 | } |
108 | } | 131 | } |
@@ -158,14 +181,15 @@ public class MapTestEnvironment<K, V> { | |||
158 | } | 181 | } |
159 | } | 182 | } |
160 | 183 | ||
161 | public static <K,V> void checkOrder(String scenario, VersionedMap<K,V> versionedMap) { | 184 | public static <K, V> void checkOrder(String scenario, VersionedMap<K, V> versionedMap) { |
162 | K previous = null; | 185 | K previous = null; |
163 | Cursor<K, V> cursor = versionedMap.getAll(); | 186 | Cursor<K, V> cursor = versionedMap.getAll(); |
164 | while(cursor.move()) { | 187 | while (cursor.move()) { |
165 | System.out.println(cursor.getKey() + " " + ((VersionedMapImpl<K, V>) versionedMap).getHashProvider().getHash(cursor.getKey(), 0)); | 188 | System.out.println(cursor.getKey() + " " + ((VersionedMapImpl<K, V>) versionedMap).getHashProvider().getHash(cursor.getKey(), 0)); |
166 | if(previous != null) { | 189 | if (previous != null) { |
167 | int comparisonResult = ((VersionedMapImpl<K, V>) versionedMap).getHashProvider().compare(previous, cursor.getKey()); | 190 | int comparisonResult = ((VersionedMapImpl<K, V>) versionedMap).getHashProvider().compare(previous, |
168 | assertTrue(comparisonResult<0,scenario+" Cursor order is not incremental!"); | 191 | cursor.getKey()); |
192 | assertTrue(comparisonResult < 0, scenario + " Cursor order is not incremental!"); | ||
169 | } | 193 | } |
170 | previous = cursor.getKey(); | 194 | previous = cursor.getKey(); |
171 | } | 195 | } |