Skip to content

Commit f72a5aa

Browse files
committed
junit: Add @FuzzTest#maxExecutions
Similar to `maxDuration`, this provides a more reliable way to limit the logical amount of fuzzing performed per run. It will be used in a test in a follow-up commit.
1 parent d624e03 commit f72a5aa

File tree

6 files changed

+29
-6
lines changed

6 files changed

+29
-6
lines changed

src/main/java/com/code_intelligence/jazzer/junit/AgentConfiguringArgumentsProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ public Stream<? extends Arguments> provideArguments(ExtensionContext extensionCo
3737
// FIXME(fmeum): Calling this here feels like a hack. There should be a lifecycle hook that runs
3838
// before the argument discovery for a ParameterizedTest is kicked off, but I haven't found
3939
// one.
40-
FuzzTestExecutor.configureAndInstallAgent(extensionContext, fuzzTest.maxDuration());
40+
FuzzTestExecutor.configureAndInstallAgent(
41+
extensionContext, fuzzTest.maxDuration(), fuzzTest.maxExecutions());
4142
return Stream.empty();
4243
}
4344
}

src/main/java/com/code_intelligence/jazzer/junit/FuzzTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,22 @@
103103
* A duration string such as "1h 2m 30s" indicating for how long the fuzz test should be executed
104104
* during fuzzing.
105105
*
106+
* <p>To remove the default limit of 5 minutes, set this element to {@code ""}.
107+
*
106108
* <p>This option has no effect during regression testing.
107109
*/
108110
String maxDuration() default "5m";
111+
112+
/**
113+
* If set to a positive number, the fuzz test function will be executed at most this many times
114+
* during fuzzing. Otherwise (default), there is no bound on the number of executions.
115+
*
116+
* <p>Prefer this element over {@link #maxDuration()} if you want to ensure comparable levels of
117+
* fuzzing across machine's with different performance characteristics.
118+
*
119+
* <p>This option has no effect during regression testing.
120+
*/
121+
long maxExecutions() default 0;
109122
}
110123

111124
// Internal use only.

src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private FuzzTestExecutor(
7070
this.isRunFromCommandLine = isRunFromCommandLine;
7171
}
7272

73-
public static FuzzTestExecutor prepare(ExtensionContext context, String maxDuration)
73+
public static FuzzTestExecutor prepare(ExtensionContext context, String maxDuration, long maxRuns)
7474
throws IOException {
7575
if (!hasBeenPrepared.compareAndSet(false, true)) {
7676
throw new IllegalStateException(
@@ -113,6 +113,9 @@ public static FuzzTestExecutor prepare(ExtensionContext context, String maxDurat
113113
}
114114

115115
libFuzzerArgs.add("-max_total_time=" + durationStringToSeconds(maxDuration));
116+
if (maxRuns > 0) {
117+
libFuzzerArgs.add("-runs=" + maxRuns);
118+
}
116119
// Disable libFuzzer's out of memory detection: It is only useful for native library fuzzing,
117120
// which we don't support without our native driver, and leads to false positives where it picks
118121
// up IntelliJ's memory usage.
@@ -256,13 +259,13 @@ private static List<String> getLibFuzzerArgs(ExtensionContext extensionContext)
256259
return args;
257260
}
258261

259-
static void configureAndInstallAgent(ExtensionContext extensionContext, String maxDuration)
260-
throws IOException {
262+
static void configureAndInstallAgent(ExtensionContext extensionContext, String maxDuration,
263+
long maxExecutions) throws IOException {
261264
if (!agentInstalled.compareAndSet(false, true)) {
262265
return;
263266
}
264267
if (Utils.isFuzzing(extensionContext)) {
265-
FuzzTestExecutor executor = prepare(extensionContext, maxDuration);
268+
FuzzTestExecutor executor = prepare(extensionContext, maxDuration, maxExecutions);
266269
extensionContext.getRoot().getStore(Namespace.GLOBAL).put(FuzzTestExecutor.class, executor);
267270
AgentConfigurator.forFuzzing(extensionContext);
268271
} else {

src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExtensions.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ public void interceptTestTemplateMethod(Invocation<Void> invocation,
4444
throws Throwable {
4545
FuzzTest fuzzTest =
4646
AnnotationSupport.findAnnotation(invocationContext.getExecutable(), FuzzTest.class).get();
47-
FuzzTestExecutor.configureAndInstallAgent(extensionContext, fuzzTest.maxDuration());
47+
FuzzTestExecutor.configureAndInstallAgent(
48+
extensionContext, fuzzTest.maxDuration(), fuzzTest.maxExecutions());
4849
// Skip the invocation of the test method with the special arguments provided by
4950
// FuzzTestArgumentsProvider and start fuzzing instead.
5051
if (Utils.isMarkedInvocation(invocationContext)) {

src/main/java/com/code_intelligence/jazzer/junit/Utils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ static boolean permissivelyParseBoolean(String value) {
243243
* allow for duration units longer than hours, so we can always prepend PT.
244244
*/
245245
static long durationStringToSeconds(String duration) {
246+
if (duration.isEmpty()) {
247+
return 0;
248+
}
246249
String isoDuration =
247250
"PT" + duration.replace("sec", "s").replace("min", "m").replace("hr", "h").replace(" ", "");
248251
return Duration.parse(isoDuration).getSeconds();

src/test/java/com/code_intelligence/jazzer/junit/UtilsTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ public class UtilsTest implements InvocationInterceptor {
5959

6060
@Test
6161
void testDurationStringToSeconds() {
62+
assertThat(durationStringToSeconds("")).isEqualTo(0);
63+
assertThat(durationStringToSeconds("0s")).isEqualTo(0);
6264
assertThat(durationStringToSeconds("1m")).isEqualTo(60);
6365
assertThat(durationStringToSeconds("1min")).isEqualTo(60);
6466
assertThat(durationStringToSeconds("1h")).isEqualTo(60 * 60);

0 commit comments

Comments
 (0)