diff options
Diffstat (limited to 'store/src/test/java/org/eclipse/viatra/solver/data/map')
12 files changed, 1259 insertions, 0 deletions
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/CommitFuzzTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/CommitFuzzTest.java new file mode 100644 index 00000000..e160df2b --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/CommitFuzzTest.java | |||
@@ -0,0 +1,95 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.fail; | ||
4 | |||
5 | import java.util.Random; | ||
6 | import java.util.stream.Stream; | ||
7 | |||
8 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
9 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
10 | import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; | ||
11 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
12 | import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; | ||
13 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
14 | import org.junit.jupiter.api.Tag; | ||
15 | import org.junit.jupiter.api.Timeout; | ||
16 | import org.junit.jupiter.params.ParameterizedTest; | ||
17 | import org.junit.jupiter.params.provider.Arguments; | ||
18 | import org.junit.jupiter.params.provider.MethodSource; | ||
19 | |||
20 | class CommitFuzzTest { | ||
21 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, | ||
22 | boolean evilHash) { | ||
23 | String[] values = MapTestEnvironment.prepareValues(maxValue); | ||
24 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | ||
25 | |||
26 | VersionedMapStore<Integer, String> store = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | ||
27 | VersionedMapImpl<Integer, String> sut = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
28 | MapTestEnvironment<Integer, String> e = new MapTestEnvironment<Integer, String>(sut); | ||
29 | |||
30 | Random r = new Random(seed); | ||
31 | |||
32 | iterativeRandomPutsAndCommits(scenario, steps, maxKey, values, e, r, commitFrequency); | ||
33 | } | ||
34 | |||
35 | private void iterativeRandomPutsAndCommits(String scenario, int steps, int maxKey, String[] values, | ||
36 | MapTestEnvironment<Integer, String> e, Random r, int commitFrequency) { | ||
37 | int stopAt = -1; | ||
38 | for (int i = 0; i < steps; i++) { | ||
39 | int index = i + 1; | ||
40 | int nextKey = r.nextInt(maxKey); | ||
41 | String nextValue = values[r.nextInt(values.length)]; | ||
42 | if (index == stopAt) { | ||
43 | System.out.println("issue!"); | ||
44 | System.out.println("State before:"); | ||
45 | e.printComparison(); | ||
46 | e.sut.prettyPrint(); | ||
47 | System.out.println("Next: put(" + nextKey + "," + nextValue + ")"); | ||
48 | } | ||
49 | try { | ||
50 | e.put(nextKey, nextValue); | ||
51 | if (index == stopAt) { | ||
52 | e.sut.prettyPrint(); | ||
53 | } | ||
54 | e.checkEquivalence(scenario + ":" + index); | ||
55 | } catch (Exception exception) { | ||
56 | exception.printStackTrace(); | ||
57 | fail(scenario + ":" + index + ": exception happened: " + exception); | ||
58 | } | ||
59 | MapTestEnvironment.printStatus(scenario, index, steps, null); | ||
60 | if (index % commitFrequency == 0) { | ||
61 | e.sut.commit(); | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | @ParameterizedTest(name = "Commit {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
67 | @MethodSource | ||
68 | @Timeout(value = 10) | ||
69 | @Tag("fuzz") | ||
70 | void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
71 | boolean evilHash) { | ||
72 | runFuzzTest("CommitS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
73 | commitFrequency, evilHash); | ||
74 | } | ||
75 | |||
76 | static Stream<Arguments> parametrizedFastFuzz() { | ||
77 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, | ||
78 | new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, | ||
79 | new Object[] { false, true }); | ||
80 | } | ||
81 | |||
82 | @ParameterizedTest(name = "Commit {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
83 | @MethodSource | ||
84 | @Tag("fuzz") | ||
85 | @Tag("slow") | ||
86 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
87 | boolean evilHash) { | ||
88 | runFuzzTest("CommitS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
89 | commitFrequency, evilHash); | ||
90 | } | ||
91 | |||
92 | static Stream<Arguments> parametrizedSlowFuzz() { | ||
93 | return FuzzTestUtils.changeStepCount(parametrizedFastFuzz(), 1); | ||
94 | } | ||
95 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/ContentEqualsFuzzTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/ContentEqualsFuzzTest.java new file mode 100644 index 00000000..5004c152 --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/ContentEqualsFuzzTest.java | |||
@@ -0,0 +1,142 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.assertEquals; | ||
4 | import static org.junit.jupiter.api.Assertions.fail; | ||
5 | |||
6 | import java.util.AbstractMap.SimpleEntry; | ||
7 | import java.util.Collections; | ||
8 | import java.util.LinkedList; | ||
9 | import java.util.List; | ||
10 | import java.util.Random; | ||
11 | import java.util.stream.Stream; | ||
12 | |||
13 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
14 | import org.eclipse.viatra.solver.data.map.Cursor; | ||
15 | import org.eclipse.viatra.solver.data.map.VersionedMap; | ||
16 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
17 | import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; | ||
18 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
19 | import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; | ||
20 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
21 | import org.junit.jupiter.api.Tag; | ||
22 | import org.junit.jupiter.api.Timeout; | ||
23 | import org.junit.jupiter.params.ParameterizedTest; | ||
24 | import org.junit.jupiter.params.provider.Arguments; | ||
25 | import org.junit.jupiter.params.provider.MethodSource; | ||
26 | |||
27 | class ContentEqualsFuzzTest { | ||
28 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, | ||
29 | boolean evilHash) { | ||
30 | String[] values = MapTestEnvironment.prepareValues(maxValue); | ||
31 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | ||
32 | |||
33 | Random r = new Random(seed); | ||
34 | |||
35 | iterativeRandomPutsAndCommitsThenCompare(scenario, chp, steps, maxKey, values, r, commitFrequency); | ||
36 | } | ||
37 | |||
38 | private void iterativeRandomPutsAndCommitsThenCompare(String scenario, ContinousHashProvider<Integer> chp, int steps, int maxKey, String[] values, Random r, int commitFrequency) { | ||
39 | |||
40 | VersionedMapStore<Integer, String> store1 = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | ||
41 | VersionedMap<Integer, String> sut1 = store1.createMap(); | ||
42 | |||
43 | // Fill one map | ||
44 | for (int i = 0; i < steps; i++) { | ||
45 | int index1 = i + 1; | ||
46 | int nextKey = r.nextInt(maxKey); | ||
47 | String nextValue = values[r.nextInt(values.length)]; | ||
48 | try { | ||
49 | sut1.put(nextKey, nextValue); | ||
50 | } catch (Exception exception) { | ||
51 | exception.printStackTrace(); | ||
52 | fail(scenario + ":" + index1 + ": exception happened: " + exception); | ||
53 | } | ||
54 | MapTestEnvironment.printStatus(scenario, index1, steps, "Fill"); | ||
55 | if (index1 % commitFrequency == 0) { | ||
56 | sut1.commit(); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | // Get the content of the first map | ||
61 | List<SimpleEntry<Integer, String>> content = new LinkedList<>(); | ||
62 | Cursor<Integer, String> cursor = sut1.getAll(); | ||
63 | while (cursor.move()) { | ||
64 | content.add(new SimpleEntry<>(cursor.getKey(), cursor.getValue())); | ||
65 | } | ||
66 | |||
67 | // Randomize the order of the content | ||
68 | Collections.shuffle(content, r); | ||
69 | |||
70 | VersionedMapStore<Integer, String> store2 = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | ||
71 | VersionedMap<Integer, String> sut2 = store2.createMap(); | ||
72 | int index2 = 1; | ||
73 | for (SimpleEntry<Integer, String> entry : content) { | ||
74 | sut2.put(entry.getKey(), entry.getValue()); | ||
75 | if(index2++%commitFrequency == 0) | ||
76 | sut2.commit(); | ||
77 | } | ||
78 | |||
79 | // Check the integrity of the maps | ||
80 | ((VersionedMapImpl<Integer,String>) sut1).checkIntegrity(); | ||
81 | ((VersionedMapImpl<Integer,String>) sut2).checkIntegrity(); | ||
82 | |||
83 | // // Compare the two maps | ||
84 | // By size | ||
85 | assertEquals(sut1.getSize(), content.size()); | ||
86 | assertEquals(sut2.getSize(), content.size()); | ||
87 | |||
88 | |||
89 | |||
90 | // By cursors | ||
91 | Cursor<Integer, String> cursor1 = sut1.getAll(); | ||
92 | Cursor<Integer, String> cursor2 = sut2.getAll(); | ||
93 | int index3 = 1; | ||
94 | boolean canMove = true; | ||
95 | do{ | ||
96 | boolean canMove1 = cursor1.move(); | ||
97 | boolean canMove2 = cursor2.move(); | ||
98 | assertEquals(canMove1, canMove2, scenario + ":" + index3 +" Cursors stopped at different times!"); | ||
99 | assertEquals(cursor1.getKey(), cursor2.getKey(), scenario + ":" + index3 +" Cursors have different keys!"); | ||
100 | assertEquals(cursor1.getValue(), cursor2.getValue(), scenario + ":" + index3 +" Cursors have different values!"); | ||
101 | |||
102 | canMove = canMove1; | ||
103 | MapTestEnvironment.printStatus(scenario, index3++, content.size(), "Compare"); | ||
104 | } while (canMove); | ||
105 | |||
106 | // By hashcode | ||
107 | assertEquals(sut1.hashCode(), sut2.hashCode(), "Hash codes are not equal!"); | ||
108 | |||
109 | // By equals | ||
110 | assertEquals(sut1, sut2, "Maps are not equals"); | ||
111 | } | ||
112 | |||
113 | @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
114 | @MethodSource | ||
115 | @Timeout(value = 10) | ||
116 | @Tag("fuzz") | ||
117 | void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
118 | boolean evilHash) { | ||
119 | runFuzzTest("CompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
120 | commitFrequency, evilHash); | ||
121 | } | ||
122 | |||
123 | static Stream<Arguments> parametrizedFastFuzz() { | ||
124 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, | ||
125 | new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, | ||
126 | new Object[] { false, true }); | ||
127 | } | ||
128 | |||
129 | @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
130 | @MethodSource | ||
131 | @Tag("fuzz") | ||
132 | @Tag("slow") | ||
133 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
134 | boolean evilHash) { | ||
135 | runFuzzTest("CompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
136 | commitFrequency, evilHash); | ||
137 | } | ||
138 | |||
139 | static Stream<Arguments> parametrizedSlowFuzz() { | ||
140 | return FuzzTestUtils.changeStepCount(parametrizedFastFuzz(), 1); | ||
141 | } | ||
142 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/DiffCursorFuzzTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/DiffCursorFuzzTest.java new file mode 100644 index 00000000..4b79a98a --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/DiffCursorFuzzTest.java | |||
@@ -0,0 +1,116 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.fail; | ||
4 | |||
5 | import java.util.Random; | ||
6 | import java.util.stream.Stream; | ||
7 | |||
8 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
9 | import org.eclipse.viatra.solver.data.map.DiffCursor; | ||
10 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
11 | import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; | ||
12 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
13 | import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; | ||
14 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
15 | import org.junit.jupiter.api.Tag; | ||
16 | import org.junit.jupiter.api.Timeout; | ||
17 | import org.junit.jupiter.params.ParameterizedTest; | ||
18 | import org.junit.jupiter.params.provider.Arguments; | ||
19 | import org.junit.jupiter.params.provider.MethodSource; | ||
20 | |||
21 | class DiffCursorFuzzTest { | ||
22 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, | ||
23 | boolean evilHash) { | ||
24 | String[] values = MapTestEnvironment.prepareValues(maxValue); | ||
25 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | ||
26 | |||
27 | VersionedMapStore<Integer, String> store = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | ||
28 | iterativeRandomPutsAndCommitsThenDiffcursor(scenario, store, steps, maxKey, values, seed, commitFrequency); | ||
29 | } | ||
30 | |||
31 | private void iterativeRandomPutsAndCommitsThenDiffcursor(String scenario, VersionedMapStore<Integer, String> store, | ||
32 | int steps, int maxKey, String[] values, int seed, int commitFrequency) { | ||
33 | // 1. build a map with versions | ||
34 | Random r = new Random(seed); | ||
35 | VersionedMapImpl<Integer, String> versioned = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
36 | int largestCommit = -1; | ||
37 | |||
38 | for (int i = 0; i < steps; i++) { | ||
39 | int index = i + 1; | ||
40 | int nextKey = r.nextInt(maxKey); | ||
41 | String nextValue = values[r.nextInt(values.length)]; | ||
42 | try { | ||
43 | versioned.put(nextKey, nextValue); | ||
44 | } catch (Exception exception) { | ||
45 | exception.printStackTrace(); | ||
46 | fail(scenario + ":" + index + ": exception happened: " + exception); | ||
47 | } | ||
48 | if (index % commitFrequency == 0) { | ||
49 | long version = versioned.commit(); | ||
50 | largestCommit = (int) version; | ||
51 | } | ||
52 | if (index % 10000 == 0) | ||
53 | System.out.println(scenario + ":" + index + "/" + steps + " building finished"); | ||
54 | } | ||
55 | // 2. create a non-versioned map, | ||
56 | VersionedMapImpl<Integer, String> moving = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
57 | Random r2 = new Random(seed + 1); | ||
58 | |||
59 | final int diffTravelFrequency = commitFrequency * 2; | ||
60 | for (int i = 0; i < steps; i++) { | ||
61 | int index = i + 1; | ||
62 | if (index % diffTravelFrequency == 0) { | ||
63 | // difftravel | ||
64 | long travelToVersion = r2.nextInt(largestCommit + 1); | ||
65 | DiffCursor<Integer, String> diffCursor = moving.getDiffCursor(travelToVersion); | ||
66 | moving.putAll(diffCursor); | ||
67 | |||
68 | } else { | ||
69 | // random puts | ||
70 | int nextKey = r2.nextInt(maxKey); | ||
71 | String nextValue = values[r2.nextInt(values.length)]; | ||
72 | try { | ||
73 | moving.put(nextKey, nextValue); | ||
74 | } catch (Exception exception) { | ||
75 | exception.printStackTrace(); | ||
76 | fail(scenario + ":" + index + ": exception happened: " + exception); | ||
77 | } | ||
78 | if (index % commitFrequency == 0) { | ||
79 | versioned.commit(); | ||
80 | } | ||
81 | if (index % 10000 == 0) | ||
82 | System.out.println(scenario + ":" + index + "/" + steps + " building finished"); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | } | ||
87 | |||
88 | @ParameterizedTest(name = "Mutable-Immutable Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
89 | @MethodSource | ||
90 | @Timeout(value = 10) | ||
91 | @Tag("fuzz") | ||
92 | void parametrizedFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
93 | boolean evilHash) { | ||
94 | runFuzzTest("MutableImmutableCompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, | ||
95 | noKeys, noValues, commitFrequency, evilHash); | ||
96 | } | ||
97 | |||
98 | static Stream<Arguments> parametrizedFuzz() { | ||
99 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, | ||
100 | new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, | ||
101 | new Object[] { false, true }); | ||
102 | } | ||
103 | @ParameterizedTest(name = "Mutable-Immutable Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
104 | @MethodSource | ||
105 | @Tag("fuzz") | ||
106 | @Tag("slow") | ||
107 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
108 | boolean evilHash) { | ||
109 | runFuzzTest("MutableImmutableCompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
110 | commitFrequency, evilHash); | ||
111 | } | ||
112 | |||
113 | static Stream<Arguments> parametrizedSlowFuzz() { | ||
114 | return FuzzTestUtils.changeStepCount(parametrizedFuzz(), 1); | ||
115 | } | ||
116 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadFuzzTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadFuzzTest.java new file mode 100644 index 00000000..c3a3e8ea --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadFuzzTest.java | |||
@@ -0,0 +1,96 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.assertEquals; | ||
4 | import static org.junit.jupiter.api.Assertions.fail; | ||
5 | |||
6 | import java.util.Collections; | ||
7 | import java.util.LinkedList; | ||
8 | import java.util.List; | ||
9 | import java.util.stream.Stream; | ||
10 | |||
11 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
12 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
13 | import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; | ||
14 | import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; | ||
15 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
16 | import org.junit.jupiter.api.Tag; | ||
17 | import org.junit.jupiter.api.Timeout; | ||
18 | import org.junit.jupiter.params.ParameterizedTest; | ||
19 | import org.junit.jupiter.params.provider.Arguments; | ||
20 | import org.junit.jupiter.params.provider.MethodSource; | ||
21 | |||
22 | class MultiThreadFuzzTest { | ||
23 | public static final int noThreads = 32; | ||
24 | |||
25 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, | ||
26 | boolean evilHash) { | ||
27 | String[] values = MapTestEnvironment.prepareValues(maxValue); | ||
28 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | ||
29 | |||
30 | VersionedMapStore<Integer, String> store = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | ||
31 | |||
32 | // initialize runnables | ||
33 | MultiThreadTestRunnable[] runnables = new MultiThreadTestRunnable[noThreads]; | ||
34 | for(int i = 0; i<noThreads; i++) { | ||
35 | runnables[i] = new MultiThreadTestRunnable(scenario+"-T"+(i+1), store, steps, maxKey, values, seed, commitFrequency); | ||
36 | } | ||
37 | |||
38 | // initialize threads | ||
39 | Thread[] threads = new Thread[noThreads]; | ||
40 | for(int i = 0; i<noThreads; i++) { | ||
41 | threads[i] = new Thread(runnables[i]); | ||
42 | } | ||
43 | |||
44 | // start threads; | ||
45 | for(int i = 0; i<noThreads; i++) { | ||
46 | threads[i].start(); | ||
47 | } | ||
48 | |||
49 | // wait all the threads; | ||
50 | for(int i = 0; i<noThreads; i++) { | ||
51 | try { | ||
52 | threads[i].join(); | ||
53 | } catch (InterruptedException e) { | ||
54 | fail("Thread "+i+" interrupted."); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | // collect errors | ||
59 | List<Throwable> errors = new LinkedList<>(); | ||
60 | for(int i = 0; i<noThreads; i++) { | ||
61 | errors.addAll(runnables[i].getErrors()); | ||
62 | } | ||
63 | |||
64 | assertEquals(Collections.EMPTY_LIST, errors); | ||
65 | } | ||
66 | |||
67 | @ParameterizedTest(name = "Multithread {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
68 | @MethodSource | ||
69 | @Timeout(value = 10) | ||
70 | @Tag("fuzz") | ||
71 | void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
72 | boolean evilHash) { | ||
73 | runFuzzTest("MultithreadS" + steps + "K" + noKeys + "V" + noValues + "CF" + commitFrequency + "s" + seed, seed, steps, noKeys, noValues, | ||
74 | commitFrequency, evilHash); | ||
75 | } | ||
76 | |||
77 | static Stream<Arguments> parametrizedFastFuzz() { | ||
78 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, | ||
79 | new Object[] { 2, 3 }, new Object[] { 10, 100 }, new Object[] { 1, 2, 3 }, | ||
80 | new Object[] { false, true }); | ||
81 | } | ||
82 | |||
83 | @ParameterizedTest(name = "Multithread {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
84 | @MethodSource | ||
85 | @Tag("fuzz") | ||
86 | @Tag("slow") | ||
87 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
88 | boolean evilHash) { | ||
89 | runFuzzTest("RestoreS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
90 | commitFrequency, evilHash); | ||
91 | } | ||
92 | |||
93 | static Stream<Arguments> parametrizedSlowFuzz() { | ||
94 | return FuzzTestUtils.changeStepCount(RestoreFuzzTest.parametrizedFastFuzz(), 1); | ||
95 | } | ||
96 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadTestRunnable.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadTestRunnable.java new file mode 100644 index 00000000..a18298a2 --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadTestRunnable.java | |||
@@ -0,0 +1,101 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import java.util.ArrayList; | ||
4 | import java.util.Collections; | ||
5 | import java.util.HashMap; | ||
6 | import java.util.LinkedList; | ||
7 | import java.util.List; | ||
8 | import java.util.Map; | ||
9 | import java.util.Random; | ||
10 | |||
11 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
12 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
13 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
14 | |||
15 | public class MultiThreadTestRunnable implements Runnable { | ||
16 | String scenario; | ||
17 | VersionedMapStore<Integer, String> store; | ||
18 | int steps; | ||
19 | int maxKey; | ||
20 | String[] values; | ||
21 | int seed; | ||
22 | int commitFrequency; | ||
23 | List<Throwable> errors = new LinkedList<>(); | ||
24 | |||
25 | public MultiThreadTestRunnable(String scenario, VersionedMapStore<Integer, String> store, int steps, | ||
26 | int maxKey, String[] values, int seed, int commitFrequency) { | ||
27 | super(); | ||
28 | this.scenario = scenario; | ||
29 | this.store = store; | ||
30 | this.steps = steps; | ||
31 | this.maxKey = maxKey; | ||
32 | this.values = values; | ||
33 | this.seed = seed; | ||
34 | this.commitFrequency = commitFrequency; | ||
35 | } | ||
36 | |||
37 | private void logAndThrowError(String message) { | ||
38 | AssertionError error = new AssertionError(message); | ||
39 | errors.add(error); | ||
40 | } | ||
41 | |||
42 | public List<Throwable> getErrors() { | ||
43 | return errors; | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public void run() { | ||
48 | // 1. build a map with versions | ||
49 | Random r = new Random(seed); | ||
50 | VersionedMapImpl<Integer, String> versioned = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
51 | Map<Integer, Long> index2Version = new HashMap<>(); | ||
52 | |||
53 | for (int i = 0; i < steps; i++) { | ||
54 | int index = i + 1; | ||
55 | int nextKey = r.nextInt(maxKey); | ||
56 | String nextValue = values[r.nextInt(values.length)]; | ||
57 | try { | ||
58 | versioned.put(nextKey, nextValue); | ||
59 | } catch (Exception exception) { | ||
60 | exception.printStackTrace(); | ||
61 | logAndThrowError(scenario + ":" + index + ": exception happened: " + exception); | ||
62 | } | ||
63 | if (index % commitFrequency == 0) { | ||
64 | long version = versioned.commit(); | ||
65 | index2Version.put(i, version); | ||
66 | } | ||
67 | MapTestEnvironment.printStatus(scenario, index, steps, "building"); | ||
68 | } | ||
69 | // 2. create a non-versioned | ||
70 | VersionedMapImpl<Integer, String> reference = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
71 | r = new Random(seed); | ||
72 | Random r2 = new Random(seed+1); | ||
73 | |||
74 | for (int i = 0; i < steps; i++) { | ||
75 | int index = i + 1; | ||
76 | int nextKey = r.nextInt(maxKey); | ||
77 | String nextValue = values[r.nextInt(values.length)]; | ||
78 | try { | ||
79 | reference.put(nextKey, nextValue); | ||
80 | } catch (Exception exception) { | ||
81 | exception.printStackTrace(); | ||
82 | logAndThrowError(scenario + ":" + index + ": exception happened: " + exception); | ||
83 | } | ||
84 | // go back to an existing state and compare to the reference | ||
85 | if (index % (commitFrequency) == 0) { | ||
86 | versioned.restore(index2Version.get(i)); | ||
87 | MapTestEnvironment.compareTwoMaps(scenario + ":" + index, reference, versioned,errors); | ||
88 | |||
89 | // go back to a random state (probably created by another thread) | ||
90 | List<Long> states = new ArrayList<>(store.getStates()); | ||
91 | Collections.shuffle(states, r2); | ||
92 | for(Long state : states.subList(0, Math.min(states.size(), 100))) { | ||
93 | versioned.restore(state); | ||
94 | } | ||
95 | versioned.restore(index2Version.get(i)); | ||
96 | } | ||
97 | |||
98 | MapTestEnvironment.printStatus(scenario, index, steps, "comparison"); | ||
99 | } | ||
100 | } | ||
101 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableFuzzTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableFuzzTest.java new file mode 100644 index 00000000..2d589dc9 --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableFuzzTest.java | |||
@@ -0,0 +1,91 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.fail; | ||
4 | |||
5 | import java.util.Random; | ||
6 | import java.util.stream.Stream; | ||
7 | |||
8 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
9 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
10 | import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; | ||
11 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
12 | import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; | ||
13 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
14 | import org.junit.jupiter.api.Tag; | ||
15 | import org.junit.jupiter.api.Timeout; | ||
16 | import org.junit.jupiter.params.ParameterizedTest; | ||
17 | import org.junit.jupiter.params.provider.Arguments; | ||
18 | import org.junit.jupiter.params.provider.MethodSource; | ||
19 | |||
20 | class MutableFuzzTest { | ||
21 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, boolean evilHash) { | ||
22 | String[] values = MapTestEnvironment.prepareValues(maxValue); | ||
23 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | ||
24 | |||
25 | VersionedMapStore<Integer, String> store = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | ||
26 | VersionedMapImpl<Integer, String> sut = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
27 | MapTestEnvironment<Integer, String> e = new MapTestEnvironment<Integer, String>(sut); | ||
28 | |||
29 | Random r = new Random(seed); | ||
30 | |||
31 | iterativeRandomPuts(scenario, steps, maxKey, values, e, r); | ||
32 | } | ||
33 | |||
34 | private void iterativeRandomPuts(String scenario, int steps, int maxKey, String[] values, | ||
35 | MapTestEnvironment<Integer, String> e, Random r) { | ||
36 | int stopAt = -1; | ||
37 | for (int i = 0; i < steps; i++) { | ||
38 | int index = i + 1; | ||
39 | int nextKey = r.nextInt(maxKey); | ||
40 | String nextValue = values[r.nextInt(values.length)]; | ||
41 | if (index == stopAt) { | ||
42 | System.out.println("issue!"); | ||
43 | System.out.println("State before:"); | ||
44 | e.printComparison(); | ||
45 | e.sut.prettyPrint(); | ||
46 | System.out.println("Next: put(" + nextKey + "," + nextValue + ")"); | ||
47 | } | ||
48 | try { | ||
49 | e.put(nextKey, nextValue); | ||
50 | if (index == stopAt) { | ||
51 | e.sut.prettyPrint(); | ||
52 | } | ||
53 | e.checkEquivalence(scenario + ":" + index); | ||
54 | } catch (Exception exception) { | ||
55 | exception.printStackTrace(); | ||
56 | fail(scenario + ":" + index + ": exception happened: " + exception); | ||
57 | } | ||
58 | MapTestEnvironment.printStatus(scenario, index, steps, null); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | @ParameterizedTest(name = "Mutable {index}/{0} Steps={1} Keys={2} Values={3} seed={4} evil-hash={5}") | ||
63 | @MethodSource | ||
64 | @Timeout(value = 10) | ||
65 | @Tag("fuzz") | ||
66 | void parametrizedFuzz(int test, int steps, int noKeys, int noValues, int seed, boolean evilHash) { | ||
67 | runFuzzTest( | ||
68 | "MutableS" + steps + "K" + noKeys + "V" + noValues + "s" + seed + "H" + (evilHash ? "Evil" : "Normal"), | ||
69 | seed, steps, noKeys, noValues, evilHash); | ||
70 | } | ||
71 | |||
72 | static Stream<Arguments> parametrizedFuzz() { | ||
73 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, | ||
74 | new Object[] { 3, 32, 32 * 32, 32 * 32 * 32 * 32 }, new Object[] { 2, 3 }, new Object[] { 1, 2, 3 }, | ||
75 | new Object[] { false, true }); | ||
76 | } | ||
77 | |||
78 | @ParameterizedTest(name = "Mutable {index}/{0} Steps={1} Keys={2} Values={3} seed={4} evil-hash={5}") | ||
79 | @MethodSource | ||
80 | @Tag("fuzz") | ||
81 | @Tag("slow") | ||
82 | void parametrizedSlowFuzz(int test, int steps, int noKeys, int noValues, int seed, boolean evilHash) { | ||
83 | runFuzzTest( | ||
84 | "MutableS" + steps + "K" + noKeys + "V" + noValues + "s" + seed + "H" + (evilHash ? "Evil" : "Normal"), | ||
85 | seed, steps, noKeys, noValues, evilHash); | ||
86 | } | ||
87 | |||
88 | static Stream<Arguments> parametrizedSlowFuzz() { | ||
89 | return FuzzTestUtils.changeStepCount(parametrizedFuzz(), 1); | ||
90 | } | ||
91 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableImmutableCompareFuzzTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableImmutableCompareFuzzTest.java new file mode 100644 index 00000000..cc2abfe4 --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableImmutableCompareFuzzTest.java | |||
@@ -0,0 +1,88 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.fail; | ||
4 | |||
5 | import java.util.Random; | ||
6 | import java.util.stream.Stream; | ||
7 | |||
8 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
9 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
10 | import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; | ||
11 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
12 | import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; | ||
13 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
14 | import org.junit.jupiter.api.Tag; | ||
15 | import org.junit.jupiter.api.Timeout; | ||
16 | import org.junit.jupiter.params.ParameterizedTest; | ||
17 | import org.junit.jupiter.params.provider.Arguments; | ||
18 | import org.junit.jupiter.params.provider.MethodSource; | ||
19 | |||
20 | class MutableImmutableCompareFuzzTest { | ||
21 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, | ||
22 | boolean evilHash) { | ||
23 | String[] values = MapTestEnvironment.prepareValues(maxValue); | ||
24 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | ||
25 | |||
26 | VersionedMapStore<Integer, String> store = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | ||
27 | VersionedMapImpl<Integer, String> immutable = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
28 | VersionedMapImpl<Integer, String> mutable = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
29 | |||
30 | Random r = new Random(seed); | ||
31 | |||
32 | iterativeRandomPutsAndCommitsAndCompare(scenario, immutable, mutable, steps, maxKey, values, r, | ||
33 | commitFrequency); | ||
34 | } | ||
35 | |||
36 | private void iterativeRandomPutsAndCommitsAndCompare(String scenario, VersionedMapImpl<Integer, String> immutable, | ||
37 | VersionedMapImpl<Integer, String> mutable, int steps, int maxKey, String[] values, Random r, | ||
38 | int commitFrequency) { | ||
39 | for (int i = 0; i < steps; i++) { | ||
40 | int index = i + 1; | ||
41 | int nextKey = r.nextInt(maxKey); | ||
42 | String nextValue = values[r.nextInt(values.length)]; | ||
43 | try { | ||
44 | immutable.put(nextKey, nextValue); | ||
45 | mutable.put(nextKey, nextValue); | ||
46 | } catch (Exception exception) { | ||
47 | exception.printStackTrace(); | ||
48 | fail(scenario + ":" + index + ": exception happened: " + exception); | ||
49 | } | ||
50 | if (index % commitFrequency == 0) { | ||
51 | immutable.commit(); | ||
52 | } | ||
53 | MapTestEnvironment.compareTwoMaps(scenario + ":" + index, immutable, mutable); | ||
54 | |||
55 | MapTestEnvironment.printStatus(scenario, index, steps, null); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | @ParameterizedTest(name = "Mutable-Immutable Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
60 | @MethodSource | ||
61 | @Timeout(value = 10) | ||
62 | @Tag("fuzz") | ||
63 | void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
64 | boolean evilHash) { | ||
65 | runFuzzTest("MutableImmutableCompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, | ||
66 | noKeys, noValues, commitFrequency, evilHash); | ||
67 | } | ||
68 | |||
69 | static Stream<Arguments> parametrizedFastFuzz() { | ||
70 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, | ||
71 | new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, | ||
72 | new Object[] { false, true }); | ||
73 | } | ||
74 | |||
75 | @ParameterizedTest(name = "Mutable-Immutable Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
76 | @MethodSource | ||
77 | @Tag("fuzz") | ||
78 | @Tag("slow") | ||
79 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
80 | boolean evilHash) { | ||
81 | runFuzzTest("MutableImmutableCompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, | ||
82 | noKeys, noValues, commitFrequency, evilHash); | ||
83 | } | ||
84 | |||
85 | static Stream<Arguments> parametrizedSlowFuzz() { | ||
86 | return FuzzTestUtils.changeStepCount(MutableImmutableCompareFuzzTest.parametrizedFastFuzz(), 1); | ||
87 | } | ||
88 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/RestoreFuzzTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/RestoreFuzzTest.java new file mode 100644 index 00000000..7d9f5372 --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/RestoreFuzzTest.java | |||
@@ -0,0 +1,108 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.fail; | ||
4 | |||
5 | import java.util.HashMap; | ||
6 | import java.util.Map; | ||
7 | import java.util.Random; | ||
8 | import java.util.stream.Stream; | ||
9 | |||
10 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
11 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
12 | import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; | ||
13 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
14 | import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; | ||
15 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
16 | import org.junit.jupiter.api.Tag; | ||
17 | import org.junit.jupiter.api.Timeout; | ||
18 | import org.junit.jupiter.params.ParameterizedTest; | ||
19 | import org.junit.jupiter.params.provider.Arguments; | ||
20 | import org.junit.jupiter.params.provider.MethodSource; | ||
21 | |||
22 | class RestoreFuzzTest { | ||
23 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, | ||
24 | boolean evilHash) { | ||
25 | String[] values = MapTestEnvironment.prepareValues(maxValue); | ||
26 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | ||
27 | |||
28 | VersionedMapStore<Integer, String> store = new VersionedMapStoreImpl<Integer, String>(chp, values[0]); | ||
29 | |||
30 | iterativeRandomPutsAndCommitsThenRestore(scenario, store, steps, maxKey, values, seed, commitFrequency); | ||
31 | } | ||
32 | |||
33 | private void iterativeRandomPutsAndCommitsThenRestore(String scenario, VersionedMapStore<Integer, String> store, | ||
34 | int steps, int maxKey, String[] values, int seed, int commitFrequency) { | ||
35 | // 1. build a map with versions | ||
36 | Random r = new Random(seed); | ||
37 | VersionedMapImpl<Integer, String> versioned = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
38 | Map<Integer, Long> index2Version = new HashMap<>(); | ||
39 | |||
40 | for (int i = 0; i < steps; i++) { | ||
41 | int index = i + 1; | ||
42 | int nextKey = r.nextInt(maxKey); | ||
43 | String nextValue = values[r.nextInt(values.length)]; | ||
44 | try { | ||
45 | versioned.put(nextKey, nextValue); | ||
46 | } catch (Exception exception) { | ||
47 | exception.printStackTrace(); | ||
48 | fail(scenario + ":" + index + ": exception happened: " + exception); | ||
49 | } | ||
50 | if (index % commitFrequency == 0) { | ||
51 | long version = versioned.commit(); | ||
52 | index2Version.put(i, version); | ||
53 | } | ||
54 | MapTestEnvironment.printStatus(scenario, index, steps, "building"); | ||
55 | } | ||
56 | // 2. create a non-versioned and | ||
57 | VersionedMapImpl<Integer, String> reference = (VersionedMapImpl<Integer, String>) store.createMap(); | ||
58 | r = new Random(seed); | ||
59 | |||
60 | for (int i = 0; i < steps; i++) { | ||
61 | int index = i + 1; | ||
62 | int nextKey = r.nextInt(maxKey); | ||
63 | String nextValue = values[r.nextInt(values.length)]; | ||
64 | try { | ||
65 | reference.put(nextKey, nextValue); | ||
66 | } catch (Exception exception) { | ||
67 | exception.printStackTrace(); | ||
68 | fail(scenario + ":" + index + ": exception happened: " + exception); | ||
69 | } | ||
70 | if (index % commitFrequency == 0) { | ||
71 | versioned.restore(index2Version.get(i)); | ||
72 | MapTestEnvironment.compareTwoMaps(scenario + ":" + index, reference, versioned); | ||
73 | } | ||
74 | MapTestEnvironment.printStatus(scenario, index, steps, "comparison"); | ||
75 | } | ||
76 | |||
77 | } | ||
78 | |||
79 | @ParameterizedTest(name = "Restore {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
80 | @MethodSource | ||
81 | @Timeout(value = 10) | ||
82 | @Tag("smoke") | ||
83 | void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
84 | boolean evilHash) { | ||
85 | runFuzzTest("RestoreS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
86 | commitFrequency, evilHash); | ||
87 | } | ||
88 | |||
89 | static Stream<Arguments> parametrizedFastFuzz() { | ||
90 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, | ||
91 | new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, | ||
92 | new Object[] { false, true }); | ||
93 | } | ||
94 | |||
95 | @ParameterizedTest(name = "Restore {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
96 | @MethodSource | ||
97 | @Tag("smoke") | ||
98 | @Tag("slow") | ||
99 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
100 | boolean evilHash) { | ||
101 | runFuzzTest("RestoreS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
102 | commitFrequency, evilHash); | ||
103 | } | ||
104 | |||
105 | static Stream<Arguments> parametrizedSlowFuzz() { | ||
106 | return FuzzTestUtils.changeStepCount(RestoreFuzzTest.parametrizedFastFuzz(), 1); | ||
107 | } | ||
108 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/SharedStoreFuzzTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/SharedStoreFuzzTest.java new file mode 100644 index 00000000..800308b4 --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/SharedStoreFuzzTest.java | |||
@@ -0,0 +1,112 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz; | ||
2 | |||
3 | import java.util.HashMap; | ||
4 | import java.util.LinkedList; | ||
5 | import java.util.List; | ||
6 | import java.util.Map; | ||
7 | import java.util.Random; | ||
8 | import java.util.stream.Stream; | ||
9 | |||
10 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
11 | import org.eclipse.viatra.solver.data.map.VersionedMapStore; | ||
12 | import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; | ||
13 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
14 | import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; | ||
15 | import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; | ||
16 | import org.junit.jupiter.api.Tag; | ||
17 | import org.junit.jupiter.api.Timeout; | ||
18 | import org.junit.jupiter.params.ParameterizedTest; | ||
19 | import org.junit.jupiter.params.provider.Arguments; | ||
20 | import org.junit.jupiter.params.provider.MethodSource; | ||
21 | |||
22 | class SharedStoreFuzzTest { | ||
23 | private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, | ||
24 | boolean evilHash) { | ||
25 | String[] values = MapTestEnvironment.prepareValues(maxValue); | ||
26 | ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); | ||
27 | |||
28 | List<VersionedMapStore<Integer, String>> stores = VersionedMapStoreImpl.createSharedVersionedMapStores(5, chp, values[0]); | ||
29 | |||
30 | iterativeRandomPutsAndCommitsThenRestore(scenario, stores, steps, maxKey, values, seed, commitFrequency); | ||
31 | } | ||
32 | |||
33 | private void iterativeRandomPutsAndCommitsThenRestore(String scenario, List<VersionedMapStore<Integer, String>> stores, | ||
34 | int steps, int maxKey, String[] values, int seed, int commitFrequency) { | ||
35 | // 1. maps with versions | ||
36 | Random r = new Random(seed); | ||
37 | List<VersionedMapImpl<Integer, String>> versioneds = new LinkedList<>(); | ||
38 | for(VersionedMapStore<Integer, String> store : stores) { | ||
39 | versioneds.add((VersionedMapImpl<Integer, String>) store.createMap()); | ||
40 | } | ||
41 | |||
42 | List<Map<Integer, Long>> index2Version = new LinkedList<>(); | ||
43 | for(int i = 0; i<stores.size(); i++) { | ||
44 | index2Version.add(new HashMap<>()); | ||
45 | } | ||
46 | |||
47 | for (int i = 0; i < steps; i++) { | ||
48 | int stepIndex = i + 1; | ||
49 | for (int storeIndex = 0; storeIndex<versioneds.size(); storeIndex++) { | ||
50 | int nextKey = r.nextInt(maxKey); | ||
51 | String nextValue = values[r.nextInt(values.length)]; | ||
52 | versioneds.get(storeIndex).put(nextKey, nextValue); | ||
53 | if (stepIndex % commitFrequency == 0) { | ||
54 | long version = versioneds.get(storeIndex).commit(); | ||
55 | index2Version.get(storeIndex).put(i, version); | ||
56 | } | ||
57 | MapTestEnvironment.printStatus(scenario, stepIndex, steps, "building"); | ||
58 | } | ||
59 | } | ||
60 | // 2. create a non-versioned and | ||
61 | List<VersionedMapImpl<Integer, String>> reference = new LinkedList<>(); | ||
62 | for(VersionedMapStore<Integer, String> store : stores) { | ||
63 | reference.add((VersionedMapImpl<Integer, String>) store.createMap()); | ||
64 | } | ||
65 | r = new Random(seed); | ||
66 | |||
67 | for (int i = 0; i < steps; i++) { | ||
68 | int index = i + 1; | ||
69 | for (int storeIndex = 0; storeIndex<versioneds.size(); storeIndex++) { | ||
70 | int nextKey = r.nextInt(maxKey); | ||
71 | String nextValue = values[r.nextInt(values.length)]; | ||
72 | reference.get(storeIndex).put(nextKey, nextValue); | ||
73 | if (index % commitFrequency == 0) { | ||
74 | versioneds.get(storeIndex).restore(index2Version.get(storeIndex).get(i)); | ||
75 | MapTestEnvironment.compareTwoMaps(scenario + ":" + index, reference.get(storeIndex), versioneds.get(storeIndex)); | ||
76 | } | ||
77 | } | ||
78 | MapTestEnvironment.printStatus(scenario, index, steps, "comparison"); | ||
79 | } | ||
80 | |||
81 | } | ||
82 | |||
83 | @ParameterizedTest(name = "Shared Store {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
84 | @MethodSource | ||
85 | @Timeout(value = 10) | ||
86 | @Tag("smoke") | ||
87 | void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
88 | boolean evilHash) { | ||
89 | runFuzzTest("SharedS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
90 | commitFrequency, evilHash); | ||
91 | } | ||
92 | |||
93 | static Stream<Arguments> parametrizedFastFuzz() { | ||
94 | return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, | ||
95 | new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, | ||
96 | new Object[] { false, true }); | ||
97 | } | ||
98 | |||
99 | @ParameterizedTest(name = "Shared Store {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") | ||
100 | @MethodSource | ||
101 | @Tag("smoke") | ||
102 | @Tag("slow") | ||
103 | void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, | ||
104 | boolean evilHash) { | ||
105 | runFuzzTest("SharedS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, | ||
106 | commitFrequency, evilHash); | ||
107 | } | ||
108 | |||
109 | static Stream<Arguments> parametrizedSlowFuzz() { | ||
110 | return FuzzTestUtils.changeStepCount(RestoreFuzzTest.parametrizedFastFuzz(), 1); | ||
111 | } | ||
112 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtils.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtils.java new file mode 100644 index 00000000..ec21bb7b --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtils.java | |||
@@ -0,0 +1,64 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz.utils; | ||
2 | |||
3 | import java.util.Arrays; | ||
4 | import java.util.LinkedList; | ||
5 | import java.util.List; | ||
6 | import java.util.stream.Stream; | ||
7 | |||
8 | import org.junit.jupiter.params.provider.Arguments; | ||
9 | |||
10 | public final class FuzzTestUtils { | ||
11 | public static final int FAST_STEP_COUNT = 500; | ||
12 | public static final int SLOW_STEP_COUNT = 32 * 32 * 32 * 32; | ||
13 | |||
14 | private FuzzTestUtils() { | ||
15 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
16 | } | ||
17 | |||
18 | public static Stream<Arguments> changeStepCount(Stream<Arguments> arguments, int parameterIndex) { | ||
19 | return arguments.map(x -> Arguments.of(updatedStepCount(x.get(), parameterIndex))); | ||
20 | } | ||
21 | |||
22 | public static Object[] updatedStepCount(Object[] arguments, int parameterIndex) { | ||
23 | Object[] copy = Arrays.copyOf(arguments, arguments.length); | ||
24 | copy[parameterIndex] = SLOW_STEP_COUNT; | ||
25 | return copy; | ||
26 | } | ||
27 | |||
28 | static List<List<Object>> permutationInternal(int from, Object[]... valueOption) { | ||
29 | if (valueOption.length == from) { | ||
30 | return List.of(List.of()); | ||
31 | } else { | ||
32 | Object[] permuteThis = valueOption[from]; | ||
33 | List<List<Object>> otherCombination = permutationInternal(from + 1, valueOption); | ||
34 | List<List<Object>> result = new LinkedList<>(); | ||
35 | for (Object permuteThisElement : permuteThis) { | ||
36 | for (List<Object> otherCombinationList : otherCombination) { | ||
37 | List<Object> newResult = new LinkedList<>(); | ||
38 | newResult.add(permuteThisElement); | ||
39 | newResult.addAll(otherCombinationList); | ||
40 | result.add(newResult); | ||
41 | } | ||
42 | } | ||
43 | return result; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | public static Stream<Arguments> permutation(Object[]... valueOption) { | ||
48 | List<List<Object>> permutations = permutationInternal(0, valueOption); | ||
49 | return permutations.stream().map(x -> Arguments.of(x.toArray())); | ||
50 | } | ||
51 | |||
52 | public static Stream<Arguments> permutationWithSize(Object[]... valueOption) { | ||
53 | int size = 1; | ||
54 | for (int i = 0; i < valueOption.length; i++) { | ||
55 | size *= valueOption[i].length; | ||
56 | } | ||
57 | Object[][] newValueOption = new Object[valueOption.length + 1][]; | ||
58 | newValueOption[0] = new Object[] { size }; | ||
59 | for (int i = 1; i < newValueOption.length; i++) { | ||
60 | newValueOption[i] = valueOption[i - 1]; | ||
61 | } | ||
62 | return permutation(newValueOption); | ||
63 | } | ||
64 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtilsTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtilsTest.java new file mode 100644 index 00000000..3f4214bc --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtilsTest.java | |||
@@ -0,0 +1,33 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.fuzz.utils; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.assertEquals; | ||
4 | |||
5 | import java.util.List; | ||
6 | |||
7 | import org.junit.jupiter.api.Test; | ||
8 | |||
9 | class FuzzTestUtilsTest { | ||
10 | @Test | ||
11 | void permutationInternalTest() { | ||
12 | List<List<Object>> res = FuzzTestUtils.permutationInternal(0, new Object[] { 1, 2, 3 }, | ||
13 | new Object[] { 'a', 'b', 'c' }, new Object[] { "alpha", "beta", "gamma", "delta" }); | ||
14 | assertEquals(3 * 3 * 4, res.size()); | ||
15 | } | ||
16 | |||
17 | @Test | ||
18 | void permutationTest1() { | ||
19 | var res = FuzzTestUtils.permutation(new Object[] { 1, 2, 3 }, new Object[] { 'a', 'b', 'c' }, | ||
20 | new Object[] { "alpha", "beta", "gamma", "delta" }); | ||
21 | assertEquals(3 * 3 * 4, res.count()); | ||
22 | } | ||
23 | |||
24 | @Test | ||
25 | void permutationTest2() { | ||
26 | var res = FuzzTestUtils.permutation(new Object[] { 1, 2, 3 }, new Object[] { 'a', 'b', 'c' }, | ||
27 | new Object[] { "alpha", "beta", "gamma", "delta" }); | ||
28 | var arguments = res.findFirst().get().get(); | ||
29 | assertEquals(1, arguments[0]); | ||
30 | assertEquals('a', arguments[1]); | ||
31 | assertEquals("alpha", arguments[2]); | ||
32 | } | ||
33 | } | ||
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/utils/MapTestEnvironment.java b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/utils/MapTestEnvironment.java new file mode 100644 index 00000000..4c043350 --- /dev/null +++ b/store/src/test/java/org/eclipse/viatra/solver/data/map/tests/utils/MapTestEnvironment.java | |||
@@ -0,0 +1,213 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.tests.utils; | ||
2 | |||
3 | import static org.junit.jupiter.api.Assertions.assertEquals; | ||
4 | import static org.junit.jupiter.api.Assertions.assertTrue; | ||
5 | import static org.junit.jupiter.api.Assertions.fail; | ||
6 | |||
7 | import java.util.HashMap; | ||
8 | import java.util.Iterator; | ||
9 | import java.util.List; | ||
10 | import java.util.Map; | ||
11 | import java.util.Map.Entry; | ||
12 | import java.util.TreeMap; | ||
13 | |||
14 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
15 | import org.eclipse.viatra.solver.data.map.Cursor; | ||
16 | import org.eclipse.viatra.solver.data.map.VersionedMap; | ||
17 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | ||
18 | |||
19 | public class MapTestEnvironment<K, V> { | ||
20 | public static String[] prepareValues(int maxValue) { | ||
21 | String[] values = new String[maxValue]; | ||
22 | values[0] = "DEFAULT"; | ||
23 | for (int i = 1; i < values.length; i++) { | ||
24 | values[i] = "VAL" + i; | ||
25 | } | ||
26 | return values; | ||
27 | } | ||
28 | |||
29 | public static ContinousHashProvider<Integer> prepareHashProvider(final boolean evil) { | ||
30 | // Use maxPrime = 2147483629 | ||
31 | |||
32 | ContinousHashProvider<Integer> chp = new ContinousHashProvider<Integer>() { | ||
33 | |||
34 | @Override | ||
35 | public int getHash(Integer key, int index) { | ||
36 | if (evil && index < 15 && index < key / 3) { | ||
37 | return 7; | ||
38 | } | ||
39 | int result = 1; | ||
40 | final int prime = 31; | ||
41 | |||
42 | result = prime * result + key; | ||
43 | result = prime * result + index; | ||
44 | |||
45 | return result; | ||
46 | } | ||
47 | }; | ||
48 | return chp; | ||
49 | } | ||
50 | |||
51 | public static void printStatus(String scenario, int actual, int max, String stepName) { | ||
52 | if (actual % 10000 == 0) { | ||
53 | String printStepName = stepName == null ? "" : stepName; | ||
54 | System.out.format(scenario + ":%d/%d (%d%%) " + printStepName + "%n", actual, max, actual * 100 / max); | ||
55 | } | ||
56 | |||
57 | } | ||
58 | |||
59 | public static <K, V> void compareTwoMaps(String title, VersionedMapImpl<K, V> map1, | ||
60 | VersionedMapImpl<K, V> map2) { | ||
61 | compareTwoMaps(title, map1, map2, null); | ||
62 | } | ||
63 | public static <K, V> void compareTwoMaps(String title, VersionedMapImpl<K, V> map1, | ||
64 | VersionedMapImpl<K, V> map2, List<Throwable> errors) { | ||
65 | // 1. Comparing cursors. | ||
66 | Cursor<K, V> cursor1 = map1.getAll(); | ||
67 | Cursor<K, V> cursor2 = map2.getAll(); | ||
68 | while (!cursor1.isTerminated()) { | ||
69 | if (cursor2.isTerminated()) { | ||
70 | fail("cursor 2 terminated before cursor1"); | ||
71 | } | ||
72 | assertEqualsList(cursor1.getKey(), cursor2.getKey(),"Keys not equal", errors); | ||
73 | assertEqualsList(cursor2.getValue(), cursor2.getValue(), "Values not equal", errors); | ||
74 | cursor1.move(); | ||
75 | cursor2.move(); | ||
76 | } | ||
77 | if (!cursor2.isTerminated()) | ||
78 | fail("cursor 1 terminated before cursor 2"); | ||
79 | |||
80 | // 2.1. comparing hash codes | ||
81 | assertEqualsList(map1.hashCode(), map2.hashCode(), title + ": hash code check",errors); | ||
82 | assertEqualsList(map1, map2, title + ": 1.equals(2)",errors); | ||
83 | assertEqualsList(map2, map1, title + ": 2.equals(1)",errors); | ||
84 | } | ||
85 | private static void assertEqualsList(Object o1, Object o2, String message, List<Throwable> errors) { | ||
86 | if(errors == null) { | ||
87 | assertEquals(o1, o2, message); | ||
88 | } else { | ||
89 | if(o1 != null) { | ||
90 | if(!(o1.equals(o2))) { | ||
91 | AssertionError error = new AssertionError((message != null ? message+" " : "") + "expected: " + o1 + " but was : " + o2); | ||
92 | errors.add(error); | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | public VersionedMapImpl<K, V> sut; | ||
99 | Map<K, V> oracle = new HashMap<K, V>(); | ||
100 | |||
101 | public MapTestEnvironment(VersionedMapImpl<K, V> sut) { | ||
102 | this.sut = sut; | ||
103 | } | ||
104 | |||
105 | public void put(K key, V value) { | ||
106 | V oldSutValue = sut.put(key, value); | ||
107 | V oldOracleValue; | ||
108 | if (value != sut.getDefaultValue()) { | ||
109 | oldOracleValue = oracle.put(key, value); | ||
110 | } else { | ||
111 | oldOracleValue = oracle.remove(key); | ||
112 | } | ||
113 | if(oldSutValue == sut.getDefaultValue() && oldOracleValue != null) { | ||
114 | fail("After put, SUT old value was default, but oracle old walue was " + oldOracleValue); | ||
115 | } | ||
116 | if(oldSutValue != sut.getDefaultValue()) { | ||
117 | assertEquals(oldOracleValue, oldSutValue); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | public void checkEquivalence(String title) { | ||
122 | // 0. Checking integrity | ||
123 | try { | ||
124 | sut.checkIntegrity(); | ||
125 | } catch (IllegalStateException e) { | ||
126 | fail(title + ": " + e.getMessage()); | ||
127 | } | ||
128 | |||
129 | // 1. Checking: if Reference contains <key,value> pair, then SUT contains | ||
130 | // <key,value> pair. | ||
131 | // Tests get functions | ||
132 | for (Entry<K, V> entry : oracle.entrySet()) { | ||
133 | V sutValue = sut.get(entry.getKey()); | ||
134 | V oracleValue = entry.getValue(); | ||
135 | if (sutValue != oracleValue) { | ||
136 | printComparison(); | ||
137 | fail(title + ": Non-equivalent get(" + entry.getKey() + ") results: SUT=" + sutValue + ", Oracle=" | ||
138 | + oracleValue + "!"); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | // 2. Checking: if SUT contains <key,value> pair, then Reference contains | ||
143 | // <key,value> pair. | ||
144 | // Tests iterators | ||
145 | int elementsInSutEntrySet = 0; | ||
146 | Cursor<K, V> cursor = sut.getAll(); | ||
147 | while (cursor.move()) { | ||
148 | elementsInSutEntrySet++; | ||
149 | K key = cursor.getKey(); | ||
150 | V sutValue = cursor.getValue(); | ||
151 | // System.out.println(key + " -> " + sutValue); | ||
152 | V oracleValue = oracle.get(key); | ||
153 | if (sutValue != oracleValue) { | ||
154 | printComparison(); | ||
155 | fail(title + ": Non-equivalent entry in iterator: SUT=<" + key + "," + sutValue + ">, Oracle=<" + key | ||
156 | + "," + oracleValue + ">!"); | ||
157 | } | ||
158 | |||
159 | } | ||
160 | |||
161 | // 3. Checking sizes | ||
162 | // Counting of non-default value pairs. | ||
163 | int oracleSize = oracle.entrySet().size(); | ||
164 | long sutSize = sut.getSize(); | ||
165 | if (oracleSize != sutSize || oracleSize != elementsInSutEntrySet) { | ||
166 | printComparison(); | ||
167 | fail(title + ": Non-eqivalent size() result: SUT.getSize()=" + sutSize + ", SUT.entryset.size=" | ||
168 | + elementsInSutEntrySet + ", Oracle=" + oracleSize + "!"); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | public static <K,V> void checkOrder(String scenario, VersionedMap<K,V> versionedMap) { | ||
173 | K previous = null; | ||
174 | Cursor<K, V> cursor = versionedMap.getAll(); | ||
175 | while(cursor.move()) { | ||
176 | System.out.println(cursor.getKey() + " " + ((VersionedMapImpl<K, V>) versionedMap).getHashProvider().getHash(cursor.getKey(), 0)); | ||
177 | if(previous != null) { | ||
178 | int comparisonResult = ((VersionedMapImpl<K, V>) versionedMap).getHashProvider().compare(previous, cursor.getKey()); | ||
179 | assertTrue(comparisonResult<0,scenario+" Cursor order is not incremental!"); | ||
180 | } | ||
181 | previous = cursor.getKey(); | ||
182 | } | ||
183 | System.out.println(); | ||
184 | } | ||
185 | |||
186 | public void printComparison() { | ||
187 | System.out.println("SUT:"); | ||
188 | printEntrySet(sut.getAll()); | ||
189 | System.out.println("Oracle:"); | ||
190 | printEntrySet(oracle.entrySet().iterator()); | ||
191 | } | ||
192 | |||
193 | private void printEntrySet(Iterator<Entry<K, V>> iterator) { | ||
194 | TreeMap<K, V> treemap = new TreeMap<>(); | ||
195 | while (iterator.hasNext()) { | ||
196 | Entry<K, V> entry = iterator.next(); | ||
197 | treemap.put(entry.getKey(), entry.getValue()); | ||
198 | } | ||
199 | for (Entry<K, V> e : treemap.entrySet()) { | ||
200 | System.out.println("\t" + e.getKey() + " -> " + e.getValue()); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | private void printEntrySet(Cursor<K, V> cursor) { | ||
205 | TreeMap<K, V> treemap = new TreeMap<>(); | ||
206 | while (cursor.move()) { | ||
207 | treemap.put(cursor.getKey(), cursor.getValue()); | ||
208 | } | ||
209 | for (Entry<K, V> e : treemap.entrySet()) { | ||
210 | System.out.println("\t" + e.getKey() + " -> " + e.getValue()); | ||
211 | } | ||
212 | } | ||
213 | } | ||