You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by dc...@apache.org on 2025/12/02 19:52:02 UTC
(cassandra-accord) 01/02: 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
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 fe6a693f834174df2c860b33ac40b3d0f0acad3f
Author: David Capwell <dc...@apple.com>
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: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org