aboutsummaryrefslogtreecommitdiffstats
path: root/store/src/test/java
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-09-29 02:45:57 +0200
committerLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-09-29 03:16:01 +0200
commita155f6ba02e08a75ce6e474a86900b8363f506e8 (patch)
treeb78804c1c0f0968a9625f0656e08f5dadc16924c /store/src/test/java
parentSimplify branding (diff)
downloadrefinery-a155f6ba02e08a75ce6e474a86900b8363f506e8.tar.gz
refinery-a155f6ba02e08a75ce6e474a86900b8363f506e8.tar.zst
refinery-a155f6ba02e08a75ce6e474a86900b8363f506e8.zip
build: migration to Gradle 7
Diffstat (limited to 'store/src/test/java')
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/CommitFuzzTest.java95
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/ContentEqualsFuzzTest.java142
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/DiffCursorFuzzTest.java116
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadFuzzTest.java96
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadTestRunnable.java101
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableFuzzTest.java91
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableImmutableCompareFuzzTest.java88
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/RestoreFuzzTest.java108
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/SharedStoreFuzzTest.java112
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtils.java64
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtilsTest.java33
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/map/tests/utils/MapTestEnvironment.java213
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java160
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/model/tests/ModelTest.java147
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/query/test/QueryTest.java89
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/util/CollectionsUtilTests.java77
16 files changed, 1732 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import static org.junit.jupiter.api.Assertions.fail;
4
5import java.util.Random;
6import java.util.stream.Stream;
7
8import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
9import org.eclipse.viatra.solver.data.map.VersionedMapStore;
10import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl;
11import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
12import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils;
13import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
14import org.junit.jupiter.api.Tag;
15import org.junit.jupiter.api.Timeout;
16import org.junit.jupiter.params.ParameterizedTest;
17import org.junit.jupiter.params.provider.Arguments;
18import org.junit.jupiter.params.provider.MethodSource;
19
20class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.fail;
5
6import java.util.AbstractMap.SimpleEntry;
7import java.util.Collections;
8import java.util.LinkedList;
9import java.util.List;
10import java.util.Random;
11import java.util.stream.Stream;
12
13import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
14import org.eclipse.viatra.solver.data.map.Cursor;
15import org.eclipse.viatra.solver.data.map.VersionedMap;
16import org.eclipse.viatra.solver.data.map.VersionedMapStore;
17import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl;
18import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
19import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils;
20import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
21import org.junit.jupiter.api.Tag;
22import org.junit.jupiter.api.Timeout;
23import org.junit.jupiter.params.ParameterizedTest;
24import org.junit.jupiter.params.provider.Arguments;
25import org.junit.jupiter.params.provider.MethodSource;
26
27class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import static org.junit.jupiter.api.Assertions.fail;
4
5import java.util.Random;
6import java.util.stream.Stream;
7
8import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
9import org.eclipse.viatra.solver.data.map.DiffCursor;
10import org.eclipse.viatra.solver.data.map.VersionedMapStore;
11import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl;
12import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
13import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils;
14import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
15import org.junit.jupiter.api.Tag;
16import org.junit.jupiter.api.Timeout;
17import org.junit.jupiter.params.ParameterizedTest;
18import org.junit.jupiter.params.provider.Arguments;
19import org.junit.jupiter.params.provider.MethodSource;
20
21class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.fail;
5
6import java.util.Collections;
7import java.util.LinkedList;
8import java.util.List;
9import java.util.stream.Stream;
10
11import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
12import org.eclipse.viatra.solver.data.map.VersionedMapStore;
13import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl;
14import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils;
15import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
16import org.junit.jupiter.api.Tag;
17import org.junit.jupiter.api.Timeout;
18import org.junit.jupiter.params.ParameterizedTest;
19import org.junit.jupiter.params.provider.Arguments;
20import org.junit.jupiter.params.provider.MethodSource;
21
22class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.HashMap;
6import java.util.LinkedList;
7import java.util.List;
8import java.util.Map;
9import java.util.Random;
10
11import org.eclipse.viatra.solver.data.map.VersionedMapStore;
12import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
13import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
14
15public 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import static org.junit.jupiter.api.Assertions.fail;
4
5import java.util.Random;
6import java.util.stream.Stream;
7
8import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
9import org.eclipse.viatra.solver.data.map.VersionedMapStore;
10import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl;
11import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
12import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils;
13import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
14import org.junit.jupiter.api.Tag;
15import org.junit.jupiter.api.Timeout;
16import org.junit.jupiter.params.ParameterizedTest;
17import org.junit.jupiter.params.provider.Arguments;
18import org.junit.jupiter.params.provider.MethodSource;
19
20class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import static org.junit.jupiter.api.Assertions.fail;
4
5import java.util.Random;
6import java.util.stream.Stream;
7
8import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
9import org.eclipse.viatra.solver.data.map.VersionedMapStore;
10import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl;
11import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
12import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils;
13import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
14import org.junit.jupiter.api.Tag;
15import org.junit.jupiter.api.Timeout;
16import org.junit.jupiter.params.ParameterizedTest;
17import org.junit.jupiter.params.provider.Arguments;
18import org.junit.jupiter.params.provider.MethodSource;
19
20class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import static org.junit.jupiter.api.Assertions.fail;
4
5import java.util.HashMap;
6import java.util.Map;
7import java.util.Random;
8import java.util.stream.Stream;
9
10import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
11import org.eclipse.viatra.solver.data.map.VersionedMapStore;
12import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl;
13import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
14import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils;
15import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
16import org.junit.jupiter.api.Tag;
17import org.junit.jupiter.api.Timeout;
18import org.junit.jupiter.params.ParameterizedTest;
19import org.junit.jupiter.params.provider.Arguments;
20import org.junit.jupiter.params.provider.MethodSource;
21
22class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz;
2
3import java.util.HashMap;
4import java.util.LinkedList;
5import java.util.List;
6import java.util.Map;
7import java.util.Random;
8import java.util.stream.Stream;
9
10import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
11import org.eclipse.viatra.solver.data.map.VersionedMapStore;
12import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl;
13import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
14import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils;
15import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment;
16import org.junit.jupiter.api.Tag;
17import org.junit.jupiter.api.Timeout;
18import org.junit.jupiter.params.ParameterizedTest;
19import org.junit.jupiter.params.provider.Arguments;
20import org.junit.jupiter.params.provider.MethodSource;
21
22class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz.utils;
2
3import java.util.Arrays;
4import java.util.LinkedList;
5import java.util.List;
6import java.util.stream.Stream;
7
8import org.junit.jupiter.params.provider.Arguments;
9
10public 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 @@
1package org.eclipse.viatra.solver.data.map.tests.fuzz.utils;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4
5import java.util.List;
6
7import org.junit.jupiter.api.Test;
8
9class 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 @@
1package org.eclipse.viatra.solver.data.map.tests.utils;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.assertTrue;
5import static org.junit.jupiter.api.Assertions.fail;
6
7import java.util.HashMap;
8import java.util.Iterator;
9import java.util.List;
10import java.util.Map;
11import java.util.Map.Entry;
12import java.util.TreeMap;
13
14import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
15import org.eclipse.viatra.solver.data.map.Cursor;
16import org.eclipse.viatra.solver.data.map.VersionedMap;
17import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;
18
19public 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}
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java
new file mode 100644
index 00000000..c4d98a43
--- /dev/null
+++ b/store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java
@@ -0,0 +1,160 @@
1package org.eclipse.viatra.solver.data.model.hashTests;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4
5import java.util.ArrayList;
6import java.util.LinkedList;
7import java.util.List;
8import java.util.Random;
9
10import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
11import org.eclipse.viatra.solver.data.model.Tuple;
12import org.eclipse.viatra.solver.data.model.TupleHashProvider;
13import org.eclipse.viatra.solver.data.model.TupleHashProviderBitMagic;
14import org.junit.jupiter.api.Test;
15
16class HashEfficiencyTest {
17
18 private static List<Tuple> permutations(int range, int arity) {
19 if(arity == 1) {
20 List<Tuple> result = new ArrayList<>(range);
21 for(int i=0; i<range; i++) {
22 result.add(Tuple.of(i));
23 }
24 return result;
25 } else if(arity > 1) {
26 List<Tuple> smallers = permutations(range, arity-1);
27 List<Tuple> result = new ArrayList<>(range*smallers.size());
28 for(Tuple smaller : smallers) {
29 for(int i=0; i<range; i++) {
30 int[] larger = new int[arity];
31 for(int x = 0; x<smaller.getSize(); x++) {
32 larger[x] = smaller.get(x);
33 }
34 larger[arity-1] = i;
35 result.add(Tuple.of(larger));
36 }
37 }
38 return result;
39 } else throw new IllegalArgumentException();
40 }
41
42 private static int amountToRange(int arity, int n) {
43 int range = 1;
44 while(Math.pow(range,arity)<n+0.1) {
45 range++;
46 }
47 return 1024;
48 }
49
50 public static List<Tuple> nPermutations(int arity, int n) {
51 int range = amountToRange(arity, n);
52 List<Tuple> permutations = permutations(range, arity);
53 return permutations.subList(0, n);
54 }
55
56 public static List<Tuple> nRandoms(int arity, int n, int seed) {
57 int range = amountToRange(arity, n);
58 List<Tuple> permutations = new ArrayList<>(n);
59 Random r = new Random(seed);
60 for(int i = 0; i<n; i++) {
61 int[] tuple = new int[arity];
62 for(int j=0; j<arity; j++) {
63 tuple[j] = r.nextInt(range);
64 }
65 permutations.add(Tuple.of(tuple));
66 }
67 return permutations;
68 }
69
70 @Test
71 void permutationTest() {
72 List<Tuple> p = permutations(10, 2);
73 assertEquals(p.size(),10*10);
74 }
75// private void printTuples(List<Tuple> p) {
76// for(Tuple element : p) {
77// System.out.println(element);
78// }
79// }
80 @Test
81 void nPermutationTest() {
82 final int amount = 500;
83 List<Tuple> p = nPermutations(2, amount);
84 assertEquals(amount,p.size());
85 }
86 @Test
87 void nRandomTest() {
88 final int amount = 500;
89 List<Tuple> p = nRandoms(2, amount, 1);;
90 assertEquals(amount,p.size());
91 }
92 private static double calculateHashClashes(List<Tuple> tuples, ContinousHashProvider<Tuple> chp) {
93 int sumClashes = 0;
94
95 for(int i = 0; i<tuples.size(); i++) {
96 int height = 0;
97 for(int j=0; j<tuples.size(); j++) {
98 int clashes = calculateHashClash(chp, tuples.get(i), tuples.get(j));
99 height = Math.max(height, clashes);
100 }
101 sumClashes += height;
102 }
103 return (sumClashes+0.0) / tuples.size();
104 }
105 private static int calculateHashClash(ContinousHashProvider<Tuple> chp, Tuple a, Tuple b) {
106 if(a.equals(b)) return 0;
107 final int bits = 5;
108 final int segments = Integer.SIZE/bits;
109 final int mask = (1<<bits)-1;
110 for(int i = 0;;i++) {
111 int index = i/segments;
112 int depth = i%segments;
113 int aHash = (chp.getHash(a, index)>>(depth*5))&mask;
114 int bHash = (chp.getHash(b, index)>>(depth*5))&mask;
115 if(aHash != bHash) {
116 return i+1;
117 }
118 if(i>400) {
119 throw new IllegalStateException(a+" vs "+b);
120 }
121 }
122 }
123 private static double caclulateOptimalHashClash(int size) {
124 return (Math.log(size)/Math.log(32));
125 }
126 public static void main(String[] args) {
127 List<String> hashNames = new LinkedList<>();
128 List<ContinousHashProvider<Tuple>> hashes = new LinkedList<>();
129 hashNames.add("PrimeGroup");
130 hashes.add(new TupleHashProvider());
131 hashNames.add("BitMagic");
132 hashes.add(new TupleHashProviderBitMagic());
133
134 int[] arities = new int[] {2,3,4,5};
135 int[] sizes = new int[] {32*32,32*32*8};
136
137 System.out.println("Size,Arity,DataSource,Hash,Chashes,Optimal,Badness");
138 for(int size : sizes) {
139 double optimalClashes = caclulateOptimalHashClash(size);
140 for(int arity : arities) {
141 List<String> dataSourceNames = new LinkedList<>();
142 List<List<Tuple>> dataSources = new LinkedList<>();
143
144// dataSourceNames.add("Permutation");
145// dataSources.add(nPermutations(arity, size));
146 dataSourceNames.add("Random");
147 dataSources.add(nRandoms(arity, size, 0));
148
149 for(int dataSourceIndex = 0; dataSourceIndex<dataSourceNames.size(); dataSourceIndex++) {
150 for(int hashIndex = 0; hashIndex<hashNames.size(); hashIndex++) {
151 double clashes = calculateHashClashes(dataSources.get(dataSourceIndex),hashes.get(hashIndex));
152 System.out.println(
153 size+","+arity+","+dataSourceNames.get(dataSourceIndex)+","+hashNames.get(hashIndex)+","+
154 clashes+","+optimalClashes+","+(clashes+0.0)/optimalClashes);
155 }
156 }
157 }
158 }
159 }
160}
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/model/tests/ModelTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/model/tests/ModelTest.java
new file mode 100644
index 00000000..c9bf3da9
--- /dev/null
+++ b/store/src/test/java/org/eclipse/viatra/solver/data/model/tests/ModelTest.java
@@ -0,0 +1,147 @@
1package org.eclipse.viatra.solver.data.model.tests;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.assertFalse;
5import static org.junit.jupiter.api.Assertions.assertTrue;
6
7import java.util.Set;
8
9import org.eclipse.viatra.solver.data.model.Model;
10import org.eclipse.viatra.solver.data.model.ModelStore;
11import org.eclipse.viatra.solver.data.model.ModelStoreImpl;
12import org.eclipse.viatra.solver.data.model.Tuple;
13import org.eclipse.viatra.solver.data.model.representation.Relation;
14import org.junit.jupiter.api.Assertions;
15import org.junit.jupiter.api.Test;
16
17class ModelTest {
18
19 @Test
20 void modelConstructionTest() {
21 Relation<Boolean> person = new Relation<>("Person", 1, false);
22 Relation<Boolean> friend = new Relation<>("friend", 2, false);
23
24 ModelStore store = new ModelStoreImpl(Set.of(person, friend));
25 Model model = store.createModel();
26
27 assertTrue(store.getDataRepresentations().contains(person));
28 assertTrue(store.getDataRepresentations().contains(friend));
29 assertTrue(model.getDataRepresentations().contains(person));
30 assertTrue(model.getDataRepresentations().contains(friend));
31
32 Relation<Integer> other = new Relation<Integer>("other", 2, null);
33 assertFalse(model.getDataRepresentations().contains(other));
34 }
35
36 @Test
37 void modelBuildingTest() {
38 Relation<Boolean> person = new Relation<>("Person", 1, false);
39 Relation<Integer> age = new Relation<Integer>("age", 1, null);
40 Relation<Boolean> friend = new Relation<>("friend", 2, false);
41
42 ModelStore store = new ModelStoreImpl(Set.of(person, age, friend));
43 Model model = store.createModel();
44
45 model.put(person, Tuple.of(0), true);
46 model.put(person, Tuple.of(1), true);
47 model.put(age, Tuple.of(0), 3);
48 model.put(age, Tuple.of(1), 1);
49 model.put(friend, Tuple.of(0, 1), true);
50 model.put(friend, Tuple.of(1, 0), true);
51
52 assertTrue(model.get(person, Tuple.of(0)));
53 assertTrue(model.get(person, Tuple.of(1)));
54 assertFalse(model.get(person, Tuple.of(2)));
55
56 assertEquals(3, model.get(age, Tuple.of(0)));
57 assertEquals(1, model.get(age, Tuple.of(1)));
58 assertEquals(null, model.get(age, Tuple.of(2)));
59
60 assertTrue(model.get(friend, Tuple.of(0, 1)));
61 assertFalse(model.get(friend, Tuple.of(0, 5)));
62 }
63
64 @Test
65 void modelBuildingArityFailTest() {
66 Relation<Boolean> person = new Relation<>("Person", 1, false);
67 ModelStore store = new ModelStoreImpl(Set.of(person));
68 Model model = store.createModel();
69
70 final Tuple tuple3 = Tuple.of(1, 1, 1);
71 Assertions.assertThrows(IllegalArgumentException.class, () -> model.put(person, tuple3, true));
72 Assertions.assertThrows(IllegalArgumentException.class, () -> model.get(person, tuple3));
73 }
74
75 @Test
76 void modelBuildingNullFailTest() {
77 Relation<Integer> age = new Relation<Integer>("age", 1, null);
78 ModelStore store = new ModelStoreImpl(Set.of(age));
79 Model model = store.createModel();
80
81 model.put(age, Tuple.of(1), null); // valid
82 Assertions.assertThrows(IllegalArgumentException.class, () -> model.put(age, null, 1));
83 Assertions.assertThrows(IllegalArgumentException.class, () -> model.get(age, null));
84
85 }
86
87 @Test
88 void modelUpdateTest() {
89 Relation<Boolean> person = new Relation<>("Person", 1, false);
90 Relation<Integer> age = new Relation<Integer>("age", 1, null);
91 Relation<Boolean> friend = new Relation<>("friend", 2, false);
92
93 ModelStore store = new ModelStoreImpl(Set.of(person, age, friend));
94 Model model = store.createModel();
95
96 model.put(person, Tuple.of(0), true);
97 model.put(person, Tuple.of(1), true);
98 model.put(age, Tuple.of(0), 3);
99 model.put(age, Tuple.of(1), 1);
100 model.put(friend, Tuple.of(0, 1), true);
101 model.put(friend, Tuple.of(1, 0), true);
102
103 assertEquals(3, model.get(age, Tuple.of(0)));
104 assertTrue(model.get(friend, Tuple.of(0, 1)));
105
106 model.put(age, Tuple.of(0), 4);
107 model.put(friend, Tuple.of(0, 1), false);
108
109 assertEquals(4, model.get(age, Tuple.of(0)));
110 assertFalse(model.get(friend, Tuple.of(0, 1)));
111 }
112
113 @Test
114 void restoreTest() {
115 Relation<Boolean> person = new Relation<Boolean>("Person", 1, false);
116 Relation<Boolean> friend = new Relation<Boolean>("friend", 2, false);
117
118 ModelStore store = new ModelStoreImpl(Set.of(person, friend));
119 Model model = store.createModel();
120
121 model.put(person, Tuple.of(0), true);
122 model.put(person, Tuple.of(1), true);
123 model.put(friend, Tuple.of(0, 1), true);
124 model.put(friend, Tuple.of(1, 0), true);
125 long state1 = model.commit();
126
127 assertFalse(model.get(person, Tuple.of(2)));
128 assertFalse(model.get(friend, Tuple.of(0, 2)));
129
130 model.put(person, Tuple.of(2), true);
131 model.put(friend, Tuple.of(0, 2), true);
132 long state2 = model.commit();
133
134 assertTrue(model.get(person, Tuple.of(2)));
135 assertTrue(model.get(friend, Tuple.of(0, 2)));
136
137 model.restore(state1);
138
139 assertFalse(model.get(person, Tuple.of(2)));
140 assertFalse(model.get(friend, Tuple.of(0, 2)));
141
142 model.restore(state2);
143
144 assertTrue(model.get(person, Tuple.of(2)));
145 assertTrue(model.get(friend, Tuple.of(0, 2)));
146 }
147}
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/query/test/QueryTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/query/test/QueryTest.java
new file mode 100644
index 00000000..182f6c94
--- /dev/null
+++ b/store/src/test/java/org/eclipse/viatra/solver/data/query/test/QueryTest.java
@@ -0,0 +1,89 @@
1package org.eclipse.viatra.solver.data.query.test;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.assertFalse;
5import static org.junit.jupiter.api.Assertions.assertTrue;
6
7import java.util.Collection;
8import java.util.Set;
9
10import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine;
11import org.eclipse.viatra.query.runtime.api.GenericPatternMatch;
12import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher;
13import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification;
14import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
15import org.eclipse.viatra.solver.data.model.Model;
16import org.eclipse.viatra.solver.data.model.ModelStore;
17import org.eclipse.viatra.solver.data.model.ModelStoreImpl;
18import org.eclipse.viatra.solver.data.model.Tuple;
19import org.eclipse.viatra.solver.data.model.representation.Relation;
20import org.eclipse.viatra.solver.data.model.representation.TruthValue;
21import org.eclipse.viatra.solver.data.query.RelationalScope;
22import org.eclipse.viatra.solver.data.query.internal.PredicateTranslator;
23import org.eclipse.viatra.solver.data.query.view.FilteredRelationView;
24import org.eclipse.viatra.solver.data.query.view.FunctionalRelationView;
25import org.eclipse.viatra.solver.data.query.view.RelationView;
26import org.eclipse.viatra.solver.data.query.view.KeyOnlyRelationView;
27import org.junit.jupiter.api.Test;
28
29class QueryTest {
30 @Test
31 void minimalTest() {
32 Relation<Boolean> person = new Relation<>("Person", 1, false);
33
34 RelationView<Boolean> persionView = new KeyOnlyRelationView(person);
35 GenericQuerySpecification<GenericPatternMatcher> personQuery = (new PredicateTranslator("PersonQuery"))
36 .addParameter("p", persionView).addConstraint(persionView, "p").build();
37
38 ModelStore store = new ModelStoreImpl(Set.of(person));
39 Model model = store.createModel();
40
41 model.put(person, Tuple.of(0), true);
42 model.put(person, Tuple.of(1), true);
43
44 RelationalScope scope = new RelationalScope(model, Set.of(persionView));
45
46 ViatraQueryEngine engine = AdvancedViatraQueryEngine.on(scope);
47 GenericPatternMatcher personMatcher = engine.getMatcher(personQuery);
48
49 assertEquals(2, personMatcher.countMatches());
50 }
51
52 void modelBuildingTest() {
53 Relation<Boolean> person = new Relation<>("Person", 1, false);
54 Relation<Integer> age = new Relation<Integer>("age", 1, null);
55 Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.False);
56
57 ModelStore store = new ModelStoreImpl(Set.of(person, age, friend));
58 Model model = store.createModel();
59
60 model.put(person, Tuple.of(0), true);
61 model.put(person, Tuple.of(1), true);
62 model.put(age, Tuple.of(0), 3);
63 model.put(age, Tuple.of(1), 1);
64 model.put(friend, Tuple.of(0, 1), TruthValue.True);
65 model.put(friend, Tuple.of(1, 0), TruthValue.Unknown);
66
67 // Sanity check
68 assertTrue(model.get(person, Tuple.of(0)));
69 assertTrue(model.get(person, Tuple.of(1)));
70 assertFalse(model.get(person, Tuple.of(2)));
71
72 RelationView<Boolean> persionView = new KeyOnlyRelationView(person);
73 RelationView<Integer> ageView = new FunctionalRelationView<>(age);
74 RelationView<TruthValue> friendMustView = new FilteredRelationView<TruthValue>(friend, (k, v) -> v.must());
75 RelationView<TruthValue> friendMayView = new FilteredRelationView<TruthValue>(friend, (k, v) -> v.may());
76
77 RelationalScope scope = new RelationalScope(model, Set.of(persionView, ageView, friendMustView, friendMayView));
78
79 GenericQuerySpecification<GenericPatternMatcher> personQuery = (new PredicateTranslator("PersonQuery"))
80 .addParameter("p", persionView).addConstraint(persionView, "p").build();
81
82 ViatraQueryEngine engine = AdvancedViatraQueryEngine.on(scope);
83 GenericPatternMatcher personMatcher = engine.getMatcher(personQuery);
84 Collection<GenericPatternMatch> personMatches = personMatcher.getAllMatches();
85 for (GenericPatternMatch personMatch : personMatches) {
86 System.out.println(personMatch);
87 }
88 }
89} \ No newline at end of file
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/util/CollectionsUtilTests.java b/store/src/test/java/org/eclipse/viatra/solver/data/util/CollectionsUtilTests.java
new file mode 100644
index 00000000..16368912
--- /dev/null
+++ b/store/src/test/java/org/eclipse/viatra/solver/data/util/CollectionsUtilTests.java
@@ -0,0 +1,77 @@
1package org.eclipse.viatra.solver.data.util;
2
3import java.util.ArrayList;
4import java.util.Iterator;
5import java.util.List;
6import java.util.NoSuchElementException;
7
8import org.junit.jupiter.api.Assertions;
9import org.junit.jupiter.api.Test;
10
11import static org.eclipse.viatra.solver.data.util.CollectionsUtil.*;
12import static org.junit.jupiter.api.Assertions.assertEquals;
13
14class CollectionsUtilTests {
15 List<Integer> list10 = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
16 List<String> listTen = List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
17
18 private static <T> void compare(Iterable<T> a, Iterable<T> b) {
19 List<T> listA = toList(a);
20 List<T> listB = toList(b);
21 assertEquals(listA, listB);
22 }
23
24 private static <T> List<T> toList(Iterable<T> a) {
25 List<T> result = new ArrayList<T>();
26 Iterator<T> iterator = a.iterator();
27 while (iterator.hasNext()) {
28 result.add(iterator.next());
29 }
30 return result;
31 }
32
33 @Test
34 void testFilterEven() {
35 compare(List.of(2, 4, 6, 8, 10), filter(list10, (x -> x % 2 == 0)));
36 }
37
38 @Test
39 void testFilterOdd() {
40 compare(List.of(1, 3, 5, 7, 9), filter(list10, (x -> x % 2 == 1)));
41 }
42
43 @Test
44 void testFilterFalse() {
45 compare(List.of(), filter(list10, (x -> false)));
46 }
47
48 @Test
49 void testFilterTrue() {
50 compare(list10, filter(list10, (x -> true)));
51 }
52
53 @Test
54 void testFilterEmpty() {
55 compare(List.of(), filter(List.of(), (x -> true)));
56 }
57
58 @Test()
59 void testNoSuchElement() {
60 Iterable<Integer> iterable = filter(list10, (x -> x % 2 == 0));
61 Iterator<Integer> iterator = iterable.iterator();
62 while (iterator.hasNext()) {
63 iterator.next();
64 }
65 Assertions.assertThrows(NoSuchElementException.class, () -> iterator.next());
66 }
67
68 @Test()
69 void mapTest() {
70 compare(listTen, map(list10, x -> x.toString()));
71 }
72
73 @Test()
74 void mapEmtyTest() {
75 compare(List.of(), map(List.of(), x -> x.toString()));
76 }
77}