aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store/src/test
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-12-14 00:57:24 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-12-21 18:34:11 +0100
commitbfc9e33a54985797968708176690a9ecfc207f83 (patch)
tree600b4508eb1289c4e30a4f6e0aecfb9d5d56cefd /subprojects/store/src/test
parentchore(deps): bump dependencies (diff)
downloadrefinery-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')
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java56
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java66
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;
17import java.util.Random; 17import java.util.Random;
18import java.util.stream.Stream; 18import java.util.stream.Stream;
19 19
20import static org.junit.jupiter.api.Assertions.assertEquals; 20import static org.junit.jupiter.api.Assertions.*;
21import static org.junit.jupiter.api.Assertions.fail;
22 21
23class ContentEqualsFuzzTest { 22class 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 @@
1package tools.refinery.store.map.tests.utils; 1package tools.refinery.store.map.tests.utils;
2 2
3import tools.refinery.store.map.ContinousHashProvider; 3import tools.refinery.store.map.*;
4import tools.refinery.store.map.Cursor;
5import tools.refinery.store.map.VersionedMap;
6import tools.refinery.store.map.internal.VersionedMapImpl; 4import tools.refinery.store.map.internal.VersionedMapImpl;
7 5
8import java.util.*; 6import 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 }