This is an automated email from the ASF dual-hosted git repository. dcapwell pushed a commit to branch CASSANDRA-20828 in repository https://gitbox.apache.org/repos/asf/cassandra-accord.git
commit 102f81028bdbf091e952aa23199e01da4b9e0de9 Author: David Capwell <[email protected]> AuthorDate: Mon Aug 11 15:01:57 2025 -0700 CASSANDRA-20828: property testing now has a withOnlySeed which is short hand for withSeed + withExample(1). Updated gitignore to exclude build artifacts for other IDEs. Updated gradle wrapper to have a longer timeout to make CI more stable --- .../src/main/java/accord/utils/RandomSource.java | 8 +++++ accord-core/src/test/java/accord/utils/Gens.java | 3 ++ .../src/test/java/accord/utils/Property.java | 36 +++++++++++++++------- gradle/wrapper/gradle-wrapper.properties | 3 +- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/accord-core/src/main/java/accord/utils/RandomSource.java b/accord-core/src/main/java/accord/utils/RandomSource.java index 80b3cd2f..c3decc5e 100644 --- a/accord-core/src/main/java/accord/utils/RandomSource.java +++ b/accord-core/src/main/java/accord/utils/RandomSource.java @@ -292,24 +292,32 @@ public interface RandomSource default <T> T pickOrderedSet(SortedSet<T> set) { + Invariants.require(!set.isEmpty(), "can not pick from an empty collection"); + if (set.size() == 1) return Iterables.getFirst(set, null); int offset = nextInt(0, set.size()); return Iterables.get(set, offset); } default <T> T pickOrderedSet(LinkedHashSet<T> set) { + Invariants.require(!set.isEmpty(), "can not pick from an empty collection"); + if (set.size() == 1) return Iterables.getFirst(set, null); int offset = nextInt(0, set.size()); return Iterables.get(set, offset); } default <T extends Enum<T>> T pickOrderedSet(EnumSet<T> set) { + Invariants.require(!set.isEmpty(), "can not pick from an empty collection"); + if (set.size() == 1) return Iterables.getFirst(set, null); int offset = nextInt(0, set.size()); return Iterables.get(set, offset); } default <T extends Comparable<? super T>> T pickUnorderedSet(Set<T> set) { + Invariants.require(!set.isEmpty(), "can not pick from an empty collection"); + if (set.size() == 1) return Iterables.getFirst(set, null); if (set instanceof SortedSet) return pickOrderedSet((SortedSet<T>) set); List<T> values = new ArrayList<>(set); diff --git a/accord-core/src/test/java/accord/utils/Gens.java b/accord-core/src/test/java/accord/utils/Gens.java index c310fb6b..5af02308 100644 --- a/accord-core/src/test/java/accord/utils/Gens.java +++ b/accord-core/src/test/java/accord/utils/Gens.java @@ -862,6 +862,9 @@ public class Gens */ public static <T> Gen<Gen<T>> mixedDistribution(List<T> list) { + Invariants.require(!list.isEmpty(), "can not pick from an empty collection"); + if (list.size() == 1) + return i -> constant(list.get(0)); return rs -> { switch (rs.nextInt(0, 4)) { diff --git a/accord-core/src/test/java/accord/utils/Property.java b/accord-core/src/test/java/accord/utils/Property.java index 92faad08..0bd40f44 100644 --- a/accord-core/src/test/java/accord/utils/Property.java +++ b/accord-core/src/test/java/accord/utils/Property.java @@ -72,6 +72,11 @@ public class Property } @SuppressWarnings("unchecked") + public T withOnlySeed(long seed) + { + return withSeed(seed).withExamples(1); + } + public T withExamples(int examples) { if (examples <= 0) @@ -104,7 +109,7 @@ public class Property } catch (ExecutionException e) { - throw new PropertyError(propertyError(this, e.getCause())); + throw new PropertyError(propertyError(this, e.getCause()), e.getCause()); } catch (InterruptedException e) { @@ -213,10 +218,11 @@ public class Property return sb.toString(); } - private static String statefulPropertyError(StatefulBuilder input, Throwable cause, Object state, List<String> history) + private static String statefulPropertyError(StatefulBuilder input, Throwable cause, Object state, int failingStep, List<String> history) { StringBuilder sb = propertyErrorCommon(input, cause); sb.append("Steps: ").append(input.steps).append('\n'); + sb.append("Failing Step: ").append(failingStep).append('\n'); sb.append("Values:\n"); String stateStr = state == null ? null : state.toString().replace("\n", "\n\t\t"); sb.append("\tState: ").append(stateStr).append(": ").append(state == null ? "unknown type" : state.getClass().getCanonicalName()).append('\n'); @@ -493,6 +499,7 @@ public class Property { State state = null; List<String> history = new ArrayList<>(steps); + int seenCommands = 0; LongArrayList historyTiming = stepTimeout == null ? null : new LongArrayList(); try { @@ -506,7 +513,7 @@ public class Property for (int j = 0; j < steps; j++) { Gen<Command<State, SystemUnderTest, ?>> cmdGen = commands.commands(state); - Command cmd = cmdGen.next(rs); + Command<State, SystemUnderTest, ?> cmd = cmdGen.next(rs); for (int a = 0; cmd.checkPreconditions(state) != PreCheckResult.Ok && a < 42; a++) { if (a == 41) @@ -517,14 +524,16 @@ public class Property { for (Command<State, SystemUnderTest, ?> sub : ((MultistepCommand<State, SystemUnderTest>) cmd)) { + seenCommands++; history.add(sub.detailed(state)); - process(sub, state, sut, history.size(), historyTiming); + process(sub, state, sut, seenCommands, historyTiming); } } else { + seenCommands++; history.add(cmd.detailed(state)); - process(cmd, state, sut, history.size(), historyTiming); + process(cmd, state, sut, seenCommands, historyTiming); } } commands.destroySut(sut, null); @@ -542,7 +551,7 @@ public class Property } catch (Throwable t) { - throw new PropertyError(statefulPropertyError(this, t, state, maybeRewriteHistory(history, historyTiming)), t); + throw new PropertyError(statefulPropertyError(this, t, state, seenCommands, maybeRewriteHistory(history, historyTiming)), t); } if (pure) { @@ -577,8 +586,7 @@ public class Property return newHistory; } - @SuppressWarnings({ "rawtypes", "unchecked" }) - private <State, SystemUnderTest> void process(Command cmd, State state, SystemUnderTest sut, int id, @Nullable LongArrayList stepTiming) throws Throwable + private <State, SystemUnderTest> void process(Command<State, SystemUnderTest, ?> cmd, State state, SystemUnderTest sut, int id, @Nullable LongArrayList stepTiming) throws Throwable { if (stepTimeout == null) { @@ -609,8 +617,10 @@ public class Property default String detailed(State state) {return this.toString();} default void process(State state, SystemUnderTest sut) throws Throwable { - checkPostconditions(state, apply(state), - sut, run(sut)); + Result apply = apply(state); + Result run = run(sut); + checkPostconditions(state, apply, + sut, run); } } @@ -851,6 +861,7 @@ public class Property default void destroyState(State state, @Nullable Throwable cause) throws Throwable {} default void destroySut(SystemUnderTest sut, @Nullable Throwable cause) throws Throwable {} Gen<Command<State, SystemUnderTest, ?>> commands(State state) throws Throwable; + } public static <State, SystemUnderTest> CommandsBuilder<State, SystemUnderTest> commands(Supplier<Gen<State>> stateGen, Function<State, SystemUnderTest> sutFactory) @@ -907,6 +918,7 @@ public class Property this.sutFactory = sutFactory; } + public CommandsBuilder<State, SystemUnderTest> preCommands(FailingConsumer<State> preCommands) { this.preCommands = preCommands; @@ -1126,7 +1138,7 @@ public class Property for (Setup<State, SystemUnderTest> s : unknownWeights) weights.put(s, unknownWeightGen.nextInt(rs)); } - nonConditional = Gens.pick(weights); + nonConditional = weights.isEmpty() ? null : Gens.pick(weights); if (conditionalCommands != null) { conditionalWeights = new LinkedHashMap<>(); @@ -1233,6 +1245,7 @@ public class Property for (var fn : onFailures) fn.onFailure(state, sut, history, cause); } + }; } @@ -1251,4 +1264,5 @@ public class Property void accept(A a, B b) throws Throwable; } } + } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 72371299..8a9c3cdf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -17,6 +17,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip -networkTimeout=10000 +# Some CI environments have ephemeral issues fetching the gradle runtime, so increased the timeout from the default 10s to 60s to make it more stable +networkTimeout=60000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
