Skip to content

Commit

Permalink
KAFKA-12459; Use property testing library for raft event simulation t…
Browse files Browse the repository at this point in the history
…ests (apache#10323)

This patch changes the raft simulation tests to use jqwik, which is a property testing library. This provides two main benefits:

- It simplifies the randomization of test parameters. Currently the tests use a fixed set of `Random` seeds, which means that most builds are doing redundant work. We get a bigger benefit from allowing each build to test different parameterizations.
- It makes it easier to reproduce failures. Whenever a test fails, jqwik will report the random seed that failed. A developer can then modify the `@Property` annotation to use that specific seed in order to reproduce the failure.

This patch also includes an optimization for `MockLog.earliestSnapshotId` which reduces the time to run the simulation tests dramatically.

Reviewers: Ismael Juma <ismael@juma.me.uk>, Chia-Ping Tsai <chia7712@gmail.com>, José Armando García Sancio <jsancio@gmail.com>, David Jacot <djacot@confluent.io>
  • Loading branch information
hachikuji committed Mar 18, 2021
1 parent 9adfac2 commit 8ef1619
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 359 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ jmh-benchmarks/generated
jmh-benchmarks/src/main/generated
streams/src/generated
raft/src/generated
raft/.jqwik-database
core/src/generated
metadata/src/generated
4 changes: 4 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ The Apache Software Foundation (https://www.apache.org/).

This distribution has a binary dependency on jersey, which is available under the CDDL
License. The source code of jersey can be found at https://github.com/jersey/jersey/.

This distribution has a binary test dependency on jqwik, which is available under
the Eclipse Public License 2.0. The source code can be found at
https://github.com/jlink/jqwik.
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,7 @@ project(':raft') {
testImplementation project(':clients').sourceSets.test.output
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation libs.jqwik

testRuntimeOnly libs.slf4jlog4j
}
Expand Down Expand Up @@ -1308,6 +1309,12 @@ project(':raft') {
}
}

test {
useJUnitPlatform {
includeEngines 'jqwik', 'junit-jupiter'
}
}

clean.doFirst {
delete "$buildDir/kafka/"
}
Expand Down
1 change: 1 addition & 0 deletions checkstyle/import-control.xml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@
<allow pkg="org.apache.kafka.metalog" />
<allow pkg="org.apache.kafka.test"/>
<allow pkg="com.fasterxml.jackson" />
<allow pkg="net.jqwik"/>
</subpackage>

<subpackage name="snapshot">
Expand Down
2 changes: 2 additions & 0 deletions gradle/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ versions += [
jfreechart: "1.0.0",
jopt: "5.0.4",
junit: "5.7.1",
jqwik: "1.5.0",
kafka_0100: "0.10.0.1",
kafka_0101: "0.10.1.1",
kafka_0102: "0.10.2.2",
Expand Down Expand Up @@ -153,6 +154,7 @@ libs += [
junitJupiter: "org.junit.jupiter:junit-jupiter:$versions.junit",
junitJupiterApi: "org.junit.jupiter:junit-jupiter-api:$versions.junit",
junitVintageEngine: "org.junit.vintage:junit-vintage-engine:$versions.junit",
jqwik: "net.jqwik:jqwik:$versions.jqwik",
hamcrest: "org.hamcrest:hamcrest:$versions.hamcrest",
kafkaStreams_0100: "org.apache.kafka:kafka-streams:$versions.kafka_0100",
kafkaStreams_0101: "org.apache.kafka:kafka-streams:$versions.kafka_0101",
Expand Down
16 changes: 5 additions & 11 deletions raft/src/test/java/org/apache/kafka/raft/MockLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
Expand Down Expand Up @@ -404,20 +404,14 @@ public Optional<RawSnapshotReader> readSnapshot(OffsetAndEpoch snapshotId) {

@Override
public Optional<OffsetAndEpoch> latestSnapshotId() {
try {
return Optional.of(snapshots.lastKey());
} catch (NoSuchElementException e) {
return Optional.empty();
}
return Optional.ofNullable(snapshots.lastEntry())
.map(Map.Entry::getKey);
}

@Override
public Optional<OffsetAndEpoch> earliestSnapshotId() {
try {
return Optional.of(snapshots.firstKey());
} catch (NoSuchElementException e) {
return Optional.empty();
}
return Optional.ofNullable(snapshots.firstEntry())
.map(Map.Entry::getKey);
}

@Override
Expand Down
Loading

0 comments on commit 8ef1619

Please sign in to comment.