diff options
Diffstat (limited to 'store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz')
11 files changed, 1046 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 | } | ||