Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ build/
accord-core/build/
accord-maelstrom/build/
.rat-excludes.txt

# Coding tools like NeoVim and Visual Studio Code will store their metadata at the following paths
accord-core/bin/
accord-maelstrom/bin/
.project
.settings
.classpath
8 changes: 8 additions & 0 deletions accord-core/src/main/java/accord/utils/RandomSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -292,24 +292,32 @@ default long pickLong(long[] array, int offset, int length)

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);
Expand Down
3 changes: 3 additions & 0 deletions accord-core/src/test/java/accord/utils/Gens.java
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,9 @@ public static <T> Gen<Gen<T>> mixedDistribution(T... list)
*/
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))
{
Expand Down
36 changes: 25 additions & 11 deletions accord-core/src/test/java/accord/utils/Property.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ public T withSeed(long seed)
}

@SuppressWarnings("unchecked")
public T withOnlySeed(long seed)
{
return withSeed(seed).withExamples(1);
}

public T withExamples(int examples)
{
if (examples <= 0)
Expand Down Expand Up @@ -104,7 +109,7 @@ protected void checkWithTimeout(Runnable fn)
}
catch (ExecutionException e)
{
throw new PropertyError(propertyError(this, e.getCause()));
throw new PropertyError(propertyError(this, e.getCause()), e.getCause());
}
catch (InterruptedException e)
{
Expand Down Expand Up @@ -213,10 +218,11 @@ private static String propertyError(Common<?> input, Throwable cause, Object...
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');
Expand Down Expand Up @@ -493,6 +499,7 @@ public <State, SystemUnderTest> void check(Commands<State, SystemUnderTest> comm
{
State state = null;
List<String> history = new ArrayList<>(steps);
int seenCommands = 0;
LongArrayList historyTiming = stepTimeout == null ? null : new LongArrayList();
try
{
Expand All @@ -506,7 +513,7 @@ public <State, SystemUnderTest> void check(Commands<State, SystemUnderTest> comm
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)
Expand All @@ -517,14 +524,16 @@ public <State, SystemUnderTest> void check(Commands<State, SystemUnderTest> comm
{
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);
Expand All @@ -542,7 +551,7 @@ public <State, SystemUnderTest> void check(Commands<State, SystemUnderTest> comm
}
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)
{
Expand Down Expand Up @@ -577,8 +586,7 @@ private static List<String> maybeRewriteHistory(List<String> history, @Nullable
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)
{
Expand Down Expand Up @@ -609,8 +617,10 @@ default void checkPostconditions(State state, Result expected,
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);
}
}

Expand Down Expand Up @@ -851,6 +861,7 @@ default void onFailure(State state, SystemUnderTest sut, List<String> history, T
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)
Expand Down Expand Up @@ -907,6 +918,7 @@ public CommandsBuilder(Supplier<Gen<State>> stateGen, Function<State, SystemUnde
this.sutFactory = sutFactory;
}


public CommandsBuilder<State, SystemUnderTest> preCommands(FailingConsumer<State> preCommands)
{
this.preCommands = preCommands;
Expand Down Expand Up @@ -1126,7 +1138,7 @@ public Setup<State, SystemUnderTest> next(RandomSource rs)
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<>();
Expand Down Expand Up @@ -1233,6 +1245,7 @@ public void onFailure(State state, SystemUnderTest sut, List<String> history, Th
for (var fn : onFailures)
fn.onFailure(state, sut, history, cause);
}

};
}

Expand All @@ -1251,4 +1264,5 @@ public interface FailingBiConsumer<A, B>
void accept(A a, B b) throws Throwable;
}
}

}
4 changes: 4 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@
accord_group=accord
accord_artifactId=accord
accord_version=1.0-SNAPSHOT

# Some times there are ephemeral issues with fetching dependencies (namely Rat) in CI, so this bumps the timeout to 120s to try to make it more stable
systemProp.org.gradle.internal.http.connectionTimeout=120000
systemProp.org.gradle.internal.http.socketTimeout=120000
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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