From a155f6ba02e08a75ce6e474a86900b8363f506e8 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Wed, 29 Sep 2021 02:45:57 +0200 Subject: build: migration to Gradle 7 --- .../solver/data/map/tests/fuzz/CommitFuzzTest.java | 95 ++++++++++++++ .../data/map/tests/fuzz/ContentEqualsFuzzTest.java | 142 +++++++++++++++++++++ .../data/map/tests/fuzz/DiffCursorFuzzTest.java | 116 +++++++++++++++++ .../data/map/tests/fuzz/MultiThreadFuzzTest.java | 96 ++++++++++++++ .../map/tests/fuzz/MultiThreadTestRunnable.java | 101 +++++++++++++++ .../data/map/tests/fuzz/MutableFuzzTest.java | 91 +++++++++++++ .../fuzz/MutableImmutableCompareFuzzTest.java | 88 +++++++++++++ .../data/map/tests/fuzz/RestoreFuzzTest.java | 108 ++++++++++++++++ .../data/map/tests/fuzz/SharedStoreFuzzTest.java | 112 ++++++++++++++++ .../data/map/tests/fuzz/utils/FuzzTestUtils.java | 64 ++++++++++ .../map/tests/fuzz/utils/FuzzTestUtilsTest.java | 33 +++++ 11 files changed, 1046 insertions(+) create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/CommitFuzzTest.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/ContentEqualsFuzzTest.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/DiffCursorFuzzTest.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadFuzzTest.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MultiThreadTestRunnable.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableFuzzTest.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/MutableImmutableCompareFuzzTest.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/RestoreFuzzTest.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/SharedStoreFuzzTest.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtils.java create mode 100644 store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz/utils/FuzzTestUtilsTest.java (limited to 'store/src/test/java/org/eclipse/viatra/solver/data/map/tests/fuzz') 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Random; +import java.util.stream.Stream; + +import org.eclipse.viatra.solver.data.map.ContinousHashProvider; +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; +import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; +import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class CommitFuzzTest { + private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, + boolean evilHash) { + String[] values = MapTestEnvironment.prepareValues(maxValue); + ContinousHashProvider chp = MapTestEnvironment.prepareHashProvider(evilHash); + + VersionedMapStore store = new VersionedMapStoreImpl(chp, values[0]); + VersionedMapImpl sut = (VersionedMapImpl) store.createMap(); + MapTestEnvironment e = new MapTestEnvironment(sut); + + Random r = new Random(seed); + + iterativeRandomPutsAndCommits(scenario, steps, maxKey, values, e, r, commitFrequency); + } + + private void iterativeRandomPutsAndCommits(String scenario, int steps, int maxKey, String[] values, + MapTestEnvironment e, Random r, int commitFrequency) { + int stopAt = -1; + for (int i = 0; i < steps; i++) { + int index = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + if (index == stopAt) { + System.out.println("issue!"); + System.out.println("State before:"); + e.printComparison(); + e.sut.prettyPrint(); + System.out.println("Next: put(" + nextKey + "," + nextValue + ")"); + } + try { + e.put(nextKey, nextValue); + if (index == stopAt) { + e.sut.prettyPrint(); + } + e.checkEquivalence(scenario + ":" + index); + } catch (Exception exception) { + exception.printStackTrace(); + fail(scenario + ":" + index + ": exception happened: " + exception); + } + MapTestEnvironment.printStatus(scenario, index, steps, null); + if (index % commitFrequency == 0) { + e.sut.commit(); + } + } + } + + @ParameterizedTest(name = "Commit {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Timeout(value = 10) + @Tag("fuzz") + void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("CommitS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedFastFuzz() { + return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, + new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, + new Object[] { false, true }); + } + + @ParameterizedTest(name = "Commit {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Tag("fuzz") + @Tag("slow") + void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("CommitS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedSlowFuzz() { + return FuzzTestUtils.changeStepCount(parametrizedFastFuzz(), 1); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.AbstractMap.SimpleEntry; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.stream.Stream; + +import org.eclipse.viatra.solver.data.map.ContinousHashProvider; +import org.eclipse.viatra.solver.data.map.Cursor; +import org.eclipse.viatra.solver.data.map.VersionedMap; +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; +import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; +import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class ContentEqualsFuzzTest { + private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, + boolean evilHash) { + String[] values = MapTestEnvironment.prepareValues(maxValue); + ContinousHashProvider chp = MapTestEnvironment.prepareHashProvider(evilHash); + + Random r = new Random(seed); + + iterativeRandomPutsAndCommitsThenCompare(scenario, chp, steps, maxKey, values, r, commitFrequency); + } + + private void iterativeRandomPutsAndCommitsThenCompare(String scenario, ContinousHashProvider chp, int steps, int maxKey, String[] values, Random r, int commitFrequency) { + + VersionedMapStore store1 = new VersionedMapStoreImpl(chp, values[0]); + VersionedMap sut1 = store1.createMap(); + + // Fill one map + for (int i = 0; i < steps; i++) { + int index1 = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + try { + sut1.put(nextKey, nextValue); + } catch (Exception exception) { + exception.printStackTrace(); + fail(scenario + ":" + index1 + ": exception happened: " + exception); + } + MapTestEnvironment.printStatus(scenario, index1, steps, "Fill"); + if (index1 % commitFrequency == 0) { + sut1.commit(); + } + } + + // Get the content of the first map + List> content = new LinkedList<>(); + Cursor cursor = sut1.getAll(); + while (cursor.move()) { + content.add(new SimpleEntry<>(cursor.getKey(), cursor.getValue())); + } + + // Randomize the order of the content + Collections.shuffle(content, r); + + VersionedMapStore store2 = new VersionedMapStoreImpl(chp, values[0]); + VersionedMap sut2 = store2.createMap(); + int index2 = 1; + for (SimpleEntry entry : content) { + sut2.put(entry.getKey(), entry.getValue()); + if(index2++%commitFrequency == 0) + sut2.commit(); + } + + // Check the integrity of the maps + ((VersionedMapImpl) sut1).checkIntegrity(); + ((VersionedMapImpl) sut2).checkIntegrity(); + +// // Compare the two maps + // By size + assertEquals(sut1.getSize(), content.size()); + assertEquals(sut2.getSize(), content.size()); + + + + // By cursors + Cursor cursor1 = sut1.getAll(); + Cursor cursor2 = sut2.getAll(); + int index3 = 1; + boolean canMove = true; + do{ + boolean canMove1 = cursor1.move(); + boolean canMove2 = cursor2.move(); + assertEquals(canMove1, canMove2, scenario + ":" + index3 +" Cursors stopped at different times!"); + assertEquals(cursor1.getKey(), cursor2.getKey(), scenario + ":" + index3 +" Cursors have different keys!"); + assertEquals(cursor1.getValue(), cursor2.getValue(), scenario + ":" + index3 +" Cursors have different values!"); + + canMove = canMove1; + MapTestEnvironment.printStatus(scenario, index3++, content.size(), "Compare"); + } while (canMove); + + // By hashcode + assertEquals(sut1.hashCode(), sut2.hashCode(), "Hash codes are not equal!"); + + // By equals + assertEquals(sut1, sut2, "Maps are not equals"); + } + + @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Timeout(value = 10) + @Tag("fuzz") + void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("CompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedFastFuzz() { + return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, + new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, + new Object[] { false, true }); + } + + @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Tag("fuzz") + @Tag("slow") + void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("CompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedSlowFuzz() { + return FuzzTestUtils.changeStepCount(parametrizedFastFuzz(), 1); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Random; +import java.util.stream.Stream; + +import org.eclipse.viatra.solver.data.map.ContinousHashProvider; +import org.eclipse.viatra.solver.data.map.DiffCursor; +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; +import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; +import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class DiffCursorFuzzTest { + private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, + boolean evilHash) { + String[] values = MapTestEnvironment.prepareValues(maxValue); + ContinousHashProvider chp = MapTestEnvironment.prepareHashProvider(evilHash); + + VersionedMapStore store = new VersionedMapStoreImpl(chp, values[0]); + iterativeRandomPutsAndCommitsThenDiffcursor(scenario, store, steps, maxKey, values, seed, commitFrequency); + } + + private void iterativeRandomPutsAndCommitsThenDiffcursor(String scenario, VersionedMapStore store, + int steps, int maxKey, String[] values, int seed, int commitFrequency) { + // 1. build a map with versions + Random r = new Random(seed); + VersionedMapImpl versioned = (VersionedMapImpl) store.createMap(); + int largestCommit = -1; + + for (int i = 0; i < steps; i++) { + int index = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + try { + versioned.put(nextKey, nextValue); + } catch (Exception exception) { + exception.printStackTrace(); + fail(scenario + ":" + index + ": exception happened: " + exception); + } + if (index % commitFrequency == 0) { + long version = versioned.commit(); + largestCommit = (int) version; + } + if (index % 10000 == 0) + System.out.println(scenario + ":" + index + "/" + steps + " building finished"); + } + // 2. create a non-versioned map, + VersionedMapImpl moving = (VersionedMapImpl) store.createMap(); + Random r2 = new Random(seed + 1); + + final int diffTravelFrequency = commitFrequency * 2; + for (int i = 0; i < steps; i++) { + int index = i + 1; + if (index % diffTravelFrequency == 0) { + // difftravel + long travelToVersion = r2.nextInt(largestCommit + 1); + DiffCursor diffCursor = moving.getDiffCursor(travelToVersion); + moving.putAll(diffCursor); + + } else { + // random puts + int nextKey = r2.nextInt(maxKey); + String nextValue = values[r2.nextInt(values.length)]; + try { + moving.put(nextKey, nextValue); + } catch (Exception exception) { + exception.printStackTrace(); + fail(scenario + ":" + index + ": exception happened: " + exception); + } + if (index % commitFrequency == 0) { + versioned.commit(); + } + if (index % 10000 == 0) + System.out.println(scenario + ":" + index + "/" + steps + " building finished"); + } + } + + } + + @ParameterizedTest(name = "Mutable-Immutable Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Timeout(value = 10) + @Tag("fuzz") + void parametrizedFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("MutableImmutableCompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, + noKeys, noValues, commitFrequency, evilHash); + } + + static Stream parametrizedFuzz() { + return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, + new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, + new Object[] { false, true }); + } + @ParameterizedTest(name = "Mutable-Immutable Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Tag("fuzz") + @Tag("slow") + void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("MutableImmutableCompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedSlowFuzz() { + return FuzzTestUtils.changeStepCount(parametrizedFuzz(), 1); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Stream; + +import org.eclipse.viatra.solver.data.map.ContinousHashProvider; +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; +import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class MultiThreadFuzzTest { + public static final int noThreads = 32; + + private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, + boolean evilHash) { + String[] values = MapTestEnvironment.prepareValues(maxValue); + ContinousHashProvider chp = MapTestEnvironment.prepareHashProvider(evilHash); + + VersionedMapStore store = new VersionedMapStoreImpl(chp, values[0]); + + // initialize runnables + MultiThreadTestRunnable[] runnables = new MultiThreadTestRunnable[noThreads]; + for(int i = 0; i errors = new LinkedList<>(); + for(int i = 0; i parametrizedFastFuzz() { + return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, + new Object[] { 2, 3 }, new Object[] { 10, 100 }, new Object[] { 1, 2, 3 }, + new Object[] { false, true }); + } + + @ParameterizedTest(name = "Multithread {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Tag("fuzz") + @Tag("slow") + void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("RestoreS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedSlowFuzz() { + return FuzzTestUtils.changeStepCount(RestoreFuzzTest.parametrizedFastFuzz(), 1); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; + +public class MultiThreadTestRunnable implements Runnable { + String scenario; + VersionedMapStore store; + int steps; + int maxKey; + String[] values; + int seed; + int commitFrequency; + List errors = new LinkedList<>(); + + public MultiThreadTestRunnable(String scenario, VersionedMapStore store, int steps, + int maxKey, String[] values, int seed, int commitFrequency) { + super(); + this.scenario = scenario; + this.store = store; + this.steps = steps; + this.maxKey = maxKey; + this.values = values; + this.seed = seed; + this.commitFrequency = commitFrequency; + } + + private void logAndThrowError(String message) { + AssertionError error = new AssertionError(message); + errors.add(error); + } + + public List getErrors() { + return errors; + } + + @Override + public void run() { + // 1. build a map with versions + Random r = new Random(seed); + VersionedMapImpl versioned = (VersionedMapImpl) store.createMap(); + Map index2Version = new HashMap<>(); + + for (int i = 0; i < steps; i++) { + int index = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + try { + versioned.put(nextKey, nextValue); + } catch (Exception exception) { + exception.printStackTrace(); + logAndThrowError(scenario + ":" + index + ": exception happened: " + exception); + } + if (index % commitFrequency == 0) { + long version = versioned.commit(); + index2Version.put(i, version); + } + MapTestEnvironment.printStatus(scenario, index, steps, "building"); + } + // 2. create a non-versioned + VersionedMapImpl reference = (VersionedMapImpl) store.createMap(); + r = new Random(seed); + Random r2 = new Random(seed+1); + + for (int i = 0; i < steps; i++) { + int index = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + try { + reference.put(nextKey, nextValue); + } catch (Exception exception) { + exception.printStackTrace(); + logAndThrowError(scenario + ":" + index + ": exception happened: " + exception); + } + // go back to an existing state and compare to the reference + if (index % (commitFrequency) == 0) { + versioned.restore(index2Version.get(i)); + MapTestEnvironment.compareTwoMaps(scenario + ":" + index, reference, versioned,errors); + + // go back to a random state (probably created by another thread) + List states = new ArrayList<>(store.getStates()); + Collections.shuffle(states, r2); + for(Long state : states.subList(0, Math.min(states.size(), 100))) { + versioned.restore(state); + } + versioned.restore(index2Version.get(i)); + } + + MapTestEnvironment.printStatus(scenario, index, steps, "comparison"); + } + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Random; +import java.util.stream.Stream; + +import org.eclipse.viatra.solver.data.map.ContinousHashProvider; +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; +import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; +import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class MutableFuzzTest { + private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, boolean evilHash) { + String[] values = MapTestEnvironment.prepareValues(maxValue); + ContinousHashProvider chp = MapTestEnvironment.prepareHashProvider(evilHash); + + VersionedMapStore store = new VersionedMapStoreImpl(chp, values[0]); + VersionedMapImpl sut = (VersionedMapImpl) store.createMap(); + MapTestEnvironment e = new MapTestEnvironment(sut); + + Random r = new Random(seed); + + iterativeRandomPuts(scenario, steps, maxKey, values, e, r); + } + + private void iterativeRandomPuts(String scenario, int steps, int maxKey, String[] values, + MapTestEnvironment e, Random r) { + int stopAt = -1; + for (int i = 0; i < steps; i++) { + int index = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + if (index == stopAt) { + System.out.println("issue!"); + System.out.println("State before:"); + e.printComparison(); + e.sut.prettyPrint(); + System.out.println("Next: put(" + nextKey + "," + nextValue + ")"); + } + try { + e.put(nextKey, nextValue); + if (index == stopAt) { + e.sut.prettyPrint(); + } + e.checkEquivalence(scenario + ":" + index); + } catch (Exception exception) { + exception.printStackTrace(); + fail(scenario + ":" + index + ": exception happened: " + exception); + } + MapTestEnvironment.printStatus(scenario, index, steps, null); + } + } + + @ParameterizedTest(name = "Mutable {index}/{0} Steps={1} Keys={2} Values={3} seed={4} evil-hash={5}") + @MethodSource + @Timeout(value = 10) + @Tag("fuzz") + void parametrizedFuzz(int test, int steps, int noKeys, int noValues, int seed, boolean evilHash) { + runFuzzTest( + "MutableS" + steps + "K" + noKeys + "V" + noValues + "s" + seed + "H" + (evilHash ? "Evil" : "Normal"), + seed, steps, noKeys, noValues, evilHash); + } + + static Stream parametrizedFuzz() { + return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, + new Object[] { 3, 32, 32 * 32, 32 * 32 * 32 * 32 }, new Object[] { 2, 3 }, new Object[] { 1, 2, 3 }, + new Object[] { false, true }); + } + + @ParameterizedTest(name = "Mutable {index}/{0} Steps={1} Keys={2} Values={3} seed={4} evil-hash={5}") + @MethodSource + @Tag("fuzz") + @Tag("slow") + void parametrizedSlowFuzz(int test, int steps, int noKeys, int noValues, int seed, boolean evilHash) { + runFuzzTest( + "MutableS" + steps + "K" + noKeys + "V" + noValues + "s" + seed + "H" + (evilHash ? "Evil" : "Normal"), + seed, steps, noKeys, noValues, evilHash); + } + + static Stream parametrizedSlowFuzz() { + return FuzzTestUtils.changeStepCount(parametrizedFuzz(), 1); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Random; +import java.util.stream.Stream; + +import org.eclipse.viatra.solver.data.map.ContinousHashProvider; +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; +import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; +import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class MutableImmutableCompareFuzzTest { + private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, + boolean evilHash) { + String[] values = MapTestEnvironment.prepareValues(maxValue); + ContinousHashProvider chp = MapTestEnvironment.prepareHashProvider(evilHash); + + VersionedMapStore store = new VersionedMapStoreImpl(chp, values[0]); + VersionedMapImpl immutable = (VersionedMapImpl) store.createMap(); + VersionedMapImpl mutable = (VersionedMapImpl) store.createMap(); + + Random r = new Random(seed); + + iterativeRandomPutsAndCommitsAndCompare(scenario, immutable, mutable, steps, maxKey, values, r, + commitFrequency); + } + + private void iterativeRandomPutsAndCommitsAndCompare(String scenario, VersionedMapImpl immutable, + VersionedMapImpl mutable, int steps, int maxKey, String[] values, Random r, + int commitFrequency) { + for (int i = 0; i < steps; i++) { + int index = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + try { + immutable.put(nextKey, nextValue); + mutable.put(nextKey, nextValue); + } catch (Exception exception) { + exception.printStackTrace(); + fail(scenario + ":" + index + ": exception happened: " + exception); + } + if (index % commitFrequency == 0) { + immutable.commit(); + } + MapTestEnvironment.compareTwoMaps(scenario + ":" + index, immutable, mutable); + + MapTestEnvironment.printStatus(scenario, index, steps, null); + } + } + + @ParameterizedTest(name = "Mutable-Immutable Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Timeout(value = 10) + @Tag("fuzz") + void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("MutableImmutableCompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, + noKeys, noValues, commitFrequency, evilHash); + } + + static Stream parametrizedFastFuzz() { + return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, + new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, + new Object[] { false, true }); + } + + @ParameterizedTest(name = "Mutable-Immutable Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Tag("fuzz") + @Tag("slow") + void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("MutableImmutableCompareS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, + noKeys, noValues, commitFrequency, evilHash); + } + + static Stream parametrizedSlowFuzz() { + return FuzzTestUtils.changeStepCount(MutableImmutableCompareFuzzTest.parametrizedFastFuzz(), 1); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.stream.Stream; + +import org.eclipse.viatra.solver.data.map.ContinousHashProvider; +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; +import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; +import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class RestoreFuzzTest { + private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, + boolean evilHash) { + String[] values = MapTestEnvironment.prepareValues(maxValue); + ContinousHashProvider chp = MapTestEnvironment.prepareHashProvider(evilHash); + + VersionedMapStore store = new VersionedMapStoreImpl(chp, values[0]); + + iterativeRandomPutsAndCommitsThenRestore(scenario, store, steps, maxKey, values, seed, commitFrequency); + } + + private void iterativeRandomPutsAndCommitsThenRestore(String scenario, VersionedMapStore store, + int steps, int maxKey, String[] values, int seed, int commitFrequency) { + // 1. build a map with versions + Random r = new Random(seed); + VersionedMapImpl versioned = (VersionedMapImpl) store.createMap(); + Map index2Version = new HashMap<>(); + + for (int i = 0; i < steps; i++) { + int index = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + try { + versioned.put(nextKey, nextValue); + } catch (Exception exception) { + exception.printStackTrace(); + fail(scenario + ":" + index + ": exception happened: " + exception); + } + if (index % commitFrequency == 0) { + long version = versioned.commit(); + index2Version.put(i, version); + } + MapTestEnvironment.printStatus(scenario, index, steps, "building"); + } + // 2. create a non-versioned and + VersionedMapImpl reference = (VersionedMapImpl) store.createMap(); + r = new Random(seed); + + for (int i = 0; i < steps; i++) { + int index = i + 1; + int nextKey = r.nextInt(maxKey); + String nextValue = values[r.nextInt(values.length)]; + try { + reference.put(nextKey, nextValue); + } catch (Exception exception) { + exception.printStackTrace(); + fail(scenario + ":" + index + ": exception happened: " + exception); + } + if (index % commitFrequency == 0) { + versioned.restore(index2Version.get(i)); + MapTestEnvironment.compareTwoMaps(scenario + ":" + index, reference, versioned); + } + MapTestEnvironment.printStatus(scenario, index, steps, "comparison"); + } + + } + + @ParameterizedTest(name = "Restore {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Timeout(value = 10) + @Tag("smoke") + void parametrizedFastFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("RestoreS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedFastFuzz() { + return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, + new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, + new Object[] { false, true }); + } + + @ParameterizedTest(name = "Restore {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Tag("smoke") + @Tag("slow") + void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("RestoreS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedSlowFuzz() { + return FuzzTestUtils.changeStepCount(RestoreFuzzTest.parametrizedFastFuzz(), 1); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.stream.Stream; + +import org.eclipse.viatra.solver.data.map.ContinousHashProvider; +import org.eclipse.viatra.solver.data.map.VersionedMapStore; +import org.eclipse.viatra.solver.data.map.VersionedMapStoreImpl; +import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; +import org.eclipse.viatra.solver.data.map.tests.fuzz.utils.FuzzTestUtils; +import org.eclipse.viatra.solver.data.map.tests.utils.MapTestEnvironment; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class SharedStoreFuzzTest { + private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, + boolean evilHash) { + String[] values = MapTestEnvironment.prepareValues(maxValue); + ContinousHashProvider chp = MapTestEnvironment.prepareHashProvider(evilHash); + + List> stores = VersionedMapStoreImpl.createSharedVersionedMapStores(5, chp, values[0]); + + iterativeRandomPutsAndCommitsThenRestore(scenario, stores, steps, maxKey, values, seed, commitFrequency); + } + + private void iterativeRandomPutsAndCommitsThenRestore(String scenario, List> stores, + int steps, int maxKey, String[] values, int seed, int commitFrequency) { + // 1. maps with versions + Random r = new Random(seed); + List> versioneds = new LinkedList<>(); + for(VersionedMapStore store : stores) { + versioneds.add((VersionedMapImpl) store.createMap()); + } + + List> index2Version = new LinkedList<>(); + for(int i = 0; i()); + } + + for (int i = 0; i < steps; i++) { + int stepIndex = i + 1; + for (int storeIndex = 0; storeIndex> reference = new LinkedList<>(); + for(VersionedMapStore store : stores) { + reference.add((VersionedMapImpl) store.createMap()); + } + r = new Random(seed); + + for (int i = 0; i < steps; i++) { + int index = i + 1; + for (int storeIndex = 0; storeIndex parametrizedFastFuzz() { + return FuzzTestUtils.permutationWithSize(new Object[] { FuzzTestUtils.FAST_STEP_COUNT }, new Object[] { 3, 32, 32 * 32 }, + new Object[] { 2, 3 }, new Object[] { 1, 10, 100 }, new Object[] { 1, 2, 3 }, + new Object[] { false, true }); + } + + @ParameterizedTest(name = "Shared Store {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") + @MethodSource + @Tag("smoke") + @Tag("slow") + void parametrizedSlowFuzz(int tests, int steps, int noKeys, int noValues, int commitFrequency, int seed, + boolean evilHash) { + runFuzzTest("SharedS" + steps + "K" + noKeys + "V" + noValues + "s" + seed, seed, steps, noKeys, noValues, + commitFrequency, evilHash); + } + + static Stream parametrizedSlowFuzz() { + return FuzzTestUtils.changeStepCount(RestoreFuzzTest.parametrizedFastFuzz(), 1); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz.utils; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.params.provider.Arguments; + +public final class FuzzTestUtils { + public static final int FAST_STEP_COUNT = 500; + public static final int SLOW_STEP_COUNT = 32 * 32 * 32 * 32; + + private FuzzTestUtils() { + throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); + } + + public static Stream changeStepCount(Stream arguments, int parameterIndex) { + return arguments.map(x -> Arguments.of(updatedStepCount(x.get(), parameterIndex))); + } + + public static Object[] updatedStepCount(Object[] arguments, int parameterIndex) { + Object[] copy = Arrays.copyOf(arguments, arguments.length); + copy[parameterIndex] = SLOW_STEP_COUNT; + return copy; + } + + static List> permutationInternal(int from, Object[]... valueOption) { + if (valueOption.length == from) { + return List.of(List.of()); + } else { + Object[] permuteThis = valueOption[from]; + List> otherCombination = permutationInternal(from + 1, valueOption); + List> result = new LinkedList<>(); + for (Object permuteThisElement : permuteThis) { + for (List otherCombinationList : otherCombination) { + List newResult = new LinkedList<>(); + newResult.add(permuteThisElement); + newResult.addAll(otherCombinationList); + result.add(newResult); + } + } + return result; + } + } + + public static Stream permutation(Object[]... valueOption) { + List> permutations = permutationInternal(0, valueOption); + return permutations.stream().map(x -> Arguments.of(x.toArray())); + } + + public static Stream permutationWithSize(Object[]... valueOption) { + int size = 1; + for (int i = 0; i < valueOption.length; i++) { + size *= valueOption[i].length; + } + Object[][] newValueOption = new Object[valueOption.length + 1][]; + newValueOption[0] = new Object[] { size }; + for (int i = 1; i < newValueOption.length; i++) { + newValueOption[i] = valueOption[i - 1]; + } + return permutation(newValueOption); + } +} 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 @@ +package org.eclipse.viatra.solver.data.map.tests.fuzz.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +class FuzzTestUtilsTest { + @Test + void permutationInternalTest() { + List> res = FuzzTestUtils.permutationInternal(0, new Object[] { 1, 2, 3 }, + new Object[] { 'a', 'b', 'c' }, new Object[] { "alpha", "beta", "gamma", "delta" }); + assertEquals(3 * 3 * 4, res.size()); + } + + @Test + void permutationTest1() { + var res = FuzzTestUtils.permutation(new Object[] { 1, 2, 3 }, new Object[] { 'a', 'b', 'c' }, + new Object[] { "alpha", "beta", "gamma", "delta" }); + assertEquals(3 * 3 * 4, res.count()); + } + + @Test + void permutationTest2() { + var res = FuzzTestUtils.permutation(new Object[] { 1, 2, 3 }, new Object[] { 'a', 'b', 'c' }, + new Object[] { "alpha", "beta", "gamma", "delta" }); + var arguments = res.findFirst().get().get(); + assertEquals(1, arguments[0]); + assertEquals('a', arguments[1]); + assertEquals("alpha", arguments[2]); + } +} -- cgit v1.2.3-54-g00ecf