aboutsummaryrefslogtreecommitdiff
path: root/src/test/java/com/code_intelligence/jazzer/autofuzz
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/code_intelligence/jazzer/autofuzz')
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/AutofuzzCodegenVisitorTest.java43
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel93
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/BuilderPatternTest.java103
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/InterfaceCreationTest.java110
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java219
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/SettersTest.java43
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/TestHelpers.java85
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/testdata/BUILD.bazel5
-rw-r--r--src/test/java/com/code_intelligence/jazzer/autofuzz/testdata/EmployeeWithSetters.java56
9 files changed, 757 insertions, 0 deletions
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/AutofuzzCodegenVisitorTest.java b/src/test/java/com/code_intelligence/jazzer/autofuzz/AutofuzzCodegenVisitorTest.java
new file mode 100644
index 00000000..814292e6
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/AutofuzzCodegenVisitorTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.code_intelligence.jazzer.autofuzz;
+
+import static com.code_intelligence.jazzer.autofuzz.AutofuzzCodegenVisitor.escapeForLiteral;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class AutofuzzCodegenVisitorTest {
+ @Test
+ public void escapeForLiteralTest() {
+ assertEquals("\\t", escapeForLiteral("\t"));
+ assertEquals("\\\\\\t", escapeForLiteral("\\\t"));
+ assertEquals("\\b", escapeForLiteral("\b"));
+ assertEquals("\\\\\\b", escapeForLiteral("\\\b"));
+ assertEquals("\\n", escapeForLiteral("\n"));
+ assertEquals("\\\\\\n", escapeForLiteral("\\\n"));
+ assertEquals("\\r", escapeForLiteral("\r"));
+ assertEquals("\\\\\\r", escapeForLiteral("\\\r"));
+ assertEquals("\\f", escapeForLiteral("\f"));
+ assertEquals("\\\\\\f", escapeForLiteral("\\\f"));
+ assertEquals("\\'", escapeForLiteral("'"));
+ assertEquals("\\\\\\'", escapeForLiteral("\\'"));
+ assertEquals("\\\"", escapeForLiteral("\""));
+ assertEquals("\\\\\\\"", escapeForLiteral("\\\""));
+ assertEquals("\\\\", escapeForLiteral("\\"));
+ }
+}
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel b/src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel
new file mode 100644
index 00000000..a5ee59b1
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel
@@ -0,0 +1,93 @@
+java_test(
+ name = "MetaTest",
+ size = "small",
+ srcs = [
+ "MetaTest.java",
+ ],
+ env = {
+ "JAZZER_AUTOFUZZ_DEBUG": "1",
+ # Also consider implementing classes from com.code_intelligence.jazzer.*.
+ "JAZZER_AUTOFUZZ_TESTING": "1",
+ },
+ test_class = "com.code_intelligence.jazzer.autofuzz.MetaTest",
+ deps = [
+ ":test_helpers",
+ "//src/main/java/com/code_intelligence/jazzer/api",
+ "//src/main/java/com/code_intelligence/jazzer/autofuzz",
+ "@maven//:com_mikesamuel_json_sanitizer",
+ "@maven//:junit_junit",
+ ],
+)
+
+java_test(
+ name = "InterfaceCreationTest",
+ size = "small",
+ srcs = [
+ "InterfaceCreationTest.java",
+ ],
+ env = {
+ "JAZZER_AUTOFUZZ_DEBUG": "1",
+ # Also consider implementing classes from com.code_intelligence.jazzer.*.
+ "JAZZER_AUTOFUZZ_TESTING": "1",
+ },
+ test_class = "com.code_intelligence.jazzer.autofuzz.InterfaceCreationTest",
+ deps = [
+ ":test_helpers",
+ "@maven//:junit_junit",
+ ],
+)
+
+java_test(
+ name = "BuilderPatternTest",
+ size = "small",
+ srcs = [
+ "BuilderPatternTest.java",
+ ],
+ env = {
+ "JAZZER_AUTOFUZZ_DEBUG": "1",
+ },
+ test_class = "com.code_intelligence.jazzer.autofuzz.BuilderPatternTest",
+ deps = [
+ ":test_helpers",
+ "@maven//:junit_junit",
+ ],
+)
+
+java_test(
+ name = "SettersTest",
+ size = "small",
+ srcs = [
+ "SettersTest.java",
+ ],
+ env = {
+ "JAZZER_AUTOFUZZ_DEBUG": "1",
+ },
+ test_class = "com.code_intelligence.jazzer.autofuzz.SettersTest",
+ deps = [
+ ":test_helpers",
+ "//src/test/java/com/code_intelligence/jazzer/autofuzz/testdata:test_data",
+ "@maven//:junit_junit",
+ ],
+)
+
+java_test(
+ name = "AutofuzzCodegenVisitorTest",
+ srcs = [
+ "AutofuzzCodegenVisitorTest.java",
+ ],
+ test_class = "com.code_intelligence.jazzer.autofuzz.AutofuzzCodegenVisitorTest",
+ deps = [
+ "//src/main/java/com/code_intelligence/jazzer/autofuzz",
+ "@maven//:junit_junit",
+ ],
+)
+
+java_library(
+ name = "test_helpers",
+ srcs = ["TestHelpers.java"],
+ deps = [
+ "//src/main/java/com/code_intelligence/jazzer/api",
+ "//src/main/java/com/code_intelligence/jazzer/autofuzz",
+ "@maven//:junit_junit",
+ ],
+)
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/BuilderPatternTest.java b/src/test/java/com/code_intelligence/jazzer/autofuzz/BuilderPatternTest.java
new file mode 100644
index 00000000..a602d712
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/BuilderPatternTest.java
@@ -0,0 +1,103 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.code_intelligence.jazzer.autofuzz;
+
+import static com.code_intelligence.jazzer.autofuzz.TestHelpers.consumeTestCase;
+
+import java.util.Arrays;
+import java.util.Objects;
+import org.junit.Test;
+
+class Employee {
+ private final String firstName;
+ private final String lastName;
+ private final String jobTitle;
+ private final int age;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ Employee hero = (Employee) o;
+ return age == hero.age && Objects.equals(firstName, hero.firstName)
+ && Objects.equals(lastName, hero.lastName) && Objects.equals(jobTitle, hero.jobTitle);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(firstName, lastName, jobTitle, age);
+ }
+
+ private Employee(Builder builder) {
+ this.jobTitle = builder.jobTitle;
+ this.firstName = builder.firstName;
+ this.lastName = builder.lastName;
+ this.age = builder.age;
+ }
+
+ public static class Builder {
+ private final String firstName;
+ private final String lastName;
+ private String jobTitle;
+ private int age;
+
+ public Builder(String firstName, String lastName) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ public Builder withAge(int age) {
+ this.age = age;
+ return this;
+ }
+
+ public Builder withJobTitle(String jobTitle) {
+ this.jobTitle = jobTitle;
+ return this;
+ }
+
+ public Employee build() {
+ return new Employee(this);
+ }
+ }
+}
+
+public class BuilderPatternTest {
+ @Test
+ public void testBuilderPattern() {
+ consumeTestCase(new Employee.Builder("foo", "bar").withAge(20).withJobTitle("baz").build(),
+ "new com.code_intelligence.jazzer.autofuzz.Employee.Builder(\"foo\", \"bar\").withAge(20).withJobTitle(\"baz\").build()",
+ Arrays.asList((byte) 1, // do not return null
+ 0, // Select the first Builder
+ 2, // Select two Builder methods returning a builder object (fluent design)
+ 0, // Select the first build method
+ 0, // pick the first remaining builder method (withAge)
+ 0, // pick the first remaining builder method (withJobTitle)
+ 0, // pick the first build method
+ (byte) 1, // do not return null
+ 6, // remaining bytes
+ "foo", // firstName
+ (byte) 1, // do not return null
+ 6, // remaining bytes
+ "bar", // lastName
+ 20, // age
+ (byte) 1, // do not return null
+ 6, // remaining bytes
+ "baz" // jobTitle
+ ));
+ }
+}
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/InterfaceCreationTest.java b/src/test/java/com/code_intelligence/jazzer/autofuzz/InterfaceCreationTest.java
new file mode 100644
index 00000000..3fecb973
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/InterfaceCreationTest.java
@@ -0,0 +1,110 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.code_intelligence.jazzer.autofuzz;
+
+import static com.code_intelligence.jazzer.autofuzz.TestHelpers.consumeTestCase;
+
+import java.util.Arrays;
+import java.util.Objects;
+import org.junit.Test;
+
+public class InterfaceCreationTest {
+ public interface InterfaceA {
+ void foo();
+
+ void bar();
+ }
+
+ public static abstract class ClassA1 implements InterfaceA {
+ @Override
+ public void foo() {}
+ }
+
+ public static class ClassB1 extends ClassA1 {
+ int n;
+
+ public ClassB1(int _n) {
+ n = _n;
+ }
+
+ @Override
+ public void bar() {}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ ClassB1 classB1 = (ClassB1) o;
+ return n == classB1.n;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(n);
+ }
+ }
+
+ public static class ClassB2 implements InterfaceA {
+ String s;
+
+ public ClassB2(String _s) {
+ s = _s;
+ }
+
+ @Override
+ public void foo() {}
+
+ @Override
+ public void bar() {}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ ClassB2 classB2 = (ClassB2) o;
+ return Objects.equals(s, classB2.s);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(s);
+ }
+ }
+ @Test
+ public void testConsumeInterface() {
+ consumeTestCase(InterfaceA.class, new ClassB1(5),
+ "(com.code_intelligence.jazzer.autofuzz.InterfaceCreationTest.InterfaceA) new com.code_intelligence.jazzer.autofuzz.InterfaceCreationTest.ClassB1(5)",
+ Arrays.asList((byte) 1, // do not return null
+ 0, // pick ClassB1
+ (byte) 1, // do not return null
+ 0, // pick first constructor
+ 5 // arg for ClassB1 constructor
+ ));
+ consumeTestCase(InterfaceA.class, new ClassB2("test"),
+ "(com.code_intelligence.jazzer.autofuzz.InterfaceCreationTest.InterfaceA) new com.code_intelligence.jazzer.autofuzz.InterfaceCreationTest.ClassB2(\"test\")",
+ Arrays.asList((byte) 1, // do not return null
+ 1, // pick ClassB2
+ (byte) 1, // do not return null
+ 0, // pick first constructor
+ (byte) 1, // do not return null
+ 8, // remaining bytes
+ "test" // arg for ClassB2 constructor
+ ));
+ }
+}
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java b/src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java
new file mode 100644
index 00000000..d2fec3ae
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java
@@ -0,0 +1,219 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.code_intelligence.jazzer.autofuzz;
+
+import static com.code_intelligence.jazzer.autofuzz.TestHelpers.autofuzzTestCase;
+import static com.code_intelligence.jazzer.autofuzz.TestHelpers.consumeTestCase;
+import static org.junit.Assert.assertEquals;
+
+import com.code_intelligence.jazzer.api.CannedFuzzedDataProvider;
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import com.google.json.JsonSanitizer;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import org.junit.Test;
+
+public class MetaTest {
+ public enum TestEnum {
+ FOO,
+ BAR,
+ BAZ,
+ }
+
+ @Test
+ public void testConsume() throws NoSuchMethodException {
+ consumeTestCase(5, "5", Collections.singletonList(5));
+ consumeTestCase((short) 5, "(short) 5", Collections.singletonList((short) 5));
+ consumeTestCase(5L, "5L", Collections.singletonList(5L));
+ consumeTestCase(5.0F, "5.0F", Collections.singletonList(5.0F));
+ consumeTestCase('\n', "'\\n'", Collections.singletonList('\n'));
+ consumeTestCase('\'', "'\\''", Collections.singletonList('\''));
+ consumeTestCase('\\', "'\\\\'", Collections.singletonList('\\'));
+
+ String testString = "foo\n\t\\\"bar";
+ // The expected string is obtained from testString by escaping and wrapping into escaped quotes.
+ consumeTestCase(testString, "\"foo\\n\\t\\\\\\\"bar\"",
+ Arrays.asList((byte) 1, // do not return null
+ testString.length(), testString));
+
+ consumeTestCase(null, "null", Collections.singletonList((byte) 0));
+
+ boolean[] testBooleans = new boolean[] {true, false, true};
+ consumeTestCase(testBooleans, "new boolean[]{true, false, true}",
+ Arrays.asList((byte) 1, // do not return null for the array
+ 2 * 3, testBooleans));
+
+ char[] testChars = new char[] {'a', '\n', '\''};
+ consumeTestCase(testChars, "new char[]{'a', '\\n', '\\''}",
+ Arrays.asList((byte) 1, // do not return null for the array
+ 2 * 3 * Character.BYTES + Character.BYTES, testChars[0], 2 * 3 * Character.BYTES,
+ 2 * 3 * Character.BYTES, // remaining bytes, 2 times what is needed for 3 chars
+ testChars[1], testChars[2]));
+
+ char[] testNoChars = new char[] {};
+ consumeTestCase(testNoChars, "new char[]{}",
+ Arrays.asList((byte) 1, // do not return null for the array
+ 0, 'a', 0, 0));
+
+ short[] testShorts = new short[] {(short) 1, (short) 2, (short) 3};
+ consumeTestCase(testShorts, "new short[]{(short) 1, (short) 2, (short) 3}",
+ Arrays.asList((byte) 1, // do not return null for the array
+ 2 * 3 * Short.BYTES, // remaining bytes
+ testShorts));
+
+ long[] testLongs = new long[] {1L, 2L, 3L};
+ consumeTestCase(testLongs, "new long[]{1L, 2L, 3L}",
+ Arrays.asList((byte) 1, // do not return null for the array
+ 2 * 3 * Long.BYTES, // remaining bytes
+ testLongs));
+
+ consumeTestCase(new String[] {"foo", "bar", "foo\nbar"},
+ "new java.lang.String[]{\"foo\", \"bar\", \"foo\\nbar\"}",
+ Arrays.asList((byte) 1, // do not return null for the array
+ 32, // remaining bytes
+ (byte) 1, // do not return null for the string
+ 31, // remaining bytes
+ "foo",
+ 28, // remaining bytes
+ 28, // array length
+ (byte) 1, // do not return null for the string
+ 27, // remaining bytes
+ "bar",
+ (byte) 1, // do not return null for the string
+ 23, // remaining bytes
+ "foo\nbar"));
+
+ byte[] testInputStreamBytes = new byte[] {(byte) 1, (byte) 2, (byte) 3};
+ consumeTestCase(new ByteArrayInputStream(testInputStreamBytes),
+ "new java.io.ByteArrayInputStream(new byte[]{(byte) 1, (byte) 2, (byte) 3})",
+ Arrays.asList((byte) 1, // do not return null for the InputStream
+ 2 * 3, // remaining bytes (twice the desired length)
+ testInputStreamBytes));
+
+ consumeTestCase(TestEnum.BAR,
+ String.format("%s.%s", TestEnum.class.getName(), TestEnum.BAR.name()),
+ Arrays.asList((byte) 1, // do not return null for the enum value
+ 1 /* second value */
+ ));
+
+ consumeTestCase(YourAverageJavaClass.class,
+ "com.code_intelligence.jazzer.autofuzz.YourAverageJavaClass.class",
+ Collections.singletonList((byte) 1));
+
+ Type stringStringMapType =
+ MetaTest.class.getDeclaredMethod("returnsStringStringMap").getGenericReturnType();
+ Map<String, String> expectedMap =
+ java.util.stream.Stream
+ .of(new java.util.AbstractMap.SimpleEntry<>("key0", "value0"),
+ new java.util.AbstractMap.SimpleEntry<>("key1", "value1"),
+ new java.util.AbstractMap.SimpleEntry<>("key2", (java.lang.String) null))
+ .collect(java.util.HashMap::new,
+ (map, e) -> map.put(e.getKey(), e.getValue()), java.util.HashMap::putAll);
+ consumeTestCase(stringStringMapType, expectedMap,
+ "java.util.stream.Stream.<java.util.AbstractMap.SimpleEntry<java.lang.String, java.lang.String>>of(new java.util.AbstractMap.SimpleEntry<>(\"key0\", \"value0\"), new java.util.AbstractMap.SimpleEntry<>(\"key1\", \"value1\"), new java.util.AbstractMap.SimpleEntry<>(\"key2\", (java.lang.String) null)).collect(java.util.HashMap::new, (map, e) -> map.put(e.getKey(), e.getValue()), java.util.HashMap::putAll)",
+ Arrays.asList((byte) 1, // do not return null for the map
+ 32, // remaining bytes
+ (byte) 1, // do not return null for the string
+ 31, // remaining bytes
+ "key0",
+ (byte) 1, // do not return null for the string
+ 28, // remaining bytes
+ "value0",
+ 28, // remaining bytes
+ 28, // consumeArrayLength
+ (byte) 1, // do not return null for the string
+ 27, // remaining bytes
+ "key1",
+ (byte) 1, // do not return null for the string
+ 23, // remaining bytes
+ "value1",
+ (byte) 1, // do not return null for the string
+ 27, // remaining bytes
+ "key2",
+ (byte) 0 // *do* return null for the string
+ ));
+ }
+
+ private Map<String, String> returnsStringStringMap() {
+ throw new IllegalStateException(
+ "Should not be called, only exists to construct its generic return type");
+ }
+
+ public static boolean isFive(int arg) {
+ return arg == 5;
+ }
+
+ public static boolean intEquals(int arg1, int arg2) {
+ return arg1 == arg2;
+ }
+
+ @Test
+ public void testAutofuzz() throws NoSuchMethodException {
+ autofuzzTestCase(true, "com.code_intelligence.jazzer.autofuzz.MetaTest.isFive(5)",
+ MetaTest.class.getMethod("isFive", int.class), Collections.singletonList(5));
+ autofuzzTestCase(false, "com.code_intelligence.jazzer.autofuzz.MetaTest.intEquals(5, 4)",
+ MetaTest.class.getMethod("intEquals", int.class, int.class), Arrays.asList(5, 4));
+ autofuzzTestCase("foobar", "(\"foo\").concat(\"bar\")",
+ String.class.getMethod("concat", String.class),
+ Arrays.asList((byte) 1, 6, "foo", (byte) 1, 6, "bar"));
+ autofuzzTestCase("jazzer", "new java.lang.String(\"jazzer\")",
+ String.class.getConstructor(String.class), Arrays.asList((byte) 1, 12, "jazzer"));
+ autofuzzTestCase("\"jazzer\"", "com.google.json.JsonSanitizer.sanitize(\"jazzer\")",
+ JsonSanitizer.class.getMethod("sanitize", String.class),
+ Arrays.asList((byte) 1, 12, "jazzer"));
+
+ FuzzedDataProvider data =
+ CannedFuzzedDataProvider.create(Arrays.asList((byte) 1, // do not return null
+ 8, // remainingBytes
+ "buzz"));
+ assertEquals("fizzbuzz", new Meta(null).autofuzz(data, "fizz" ::concat));
+ }
+
+ // Regression test for https://github.com/CodeIntelligenceTesting/jazzer/issues/465.
+ @Test
+ public void testPrivateInterface() {
+ autofuzzTestCase(null,
+ "com.code_intelligence.jazzer.autofuzz.OpinionatedClass.doStuffWithPrivateInterface(((java.util.function.Supplier<com.code_intelligence.jazzer.autofuzz.OpinionatedClass.PublicImplementation>) (() -> {com.code_intelligence.jazzer.autofuzz.OpinionatedClass.PublicImplementation autofuzzVariable0 = new com.code_intelligence.jazzer.autofuzz.OpinionatedClass.PublicImplementation(); return autofuzzVariable0;})).get())",
+ OpinionatedClass.class.getDeclaredMethods()[0],
+ Arrays.asList((byte) 1, // do not return null
+ 0, // first (and only) class on the classpath
+ (byte) 1, // do not return null
+ 0 /* first (and only) constructor*/));
+ }
+
+ Class<?>[] returnsClassArray() {
+ throw new IllegalStateException(
+ "Should not be called, only exists to construct its generic return type");
+ }
+
+ @Test
+ public void testGetRawType() throws NoSuchMethodException {
+ Type classArrayType =
+ MetaTest.class.getDeclaredMethod("returnsClassArray").getGenericReturnType();
+ assertEquals(Class[].class, Meta.getRawType(classArrayType));
+ }
+}
+
+class OpinionatedClass {
+ public static void doStuffWithPrivateInterface(
+ @SuppressWarnings("unused") PrivateInterface thing) {}
+
+ private interface PrivateInterface {}
+
+ public static class PublicImplementation implements PrivateInterface {}
+}
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/SettersTest.java b/src/test/java/com/code_intelligence/jazzer/autofuzz/SettersTest.java
new file mode 100644
index 00000000..7c869531
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/SettersTest.java
@@ -0,0 +1,43 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.code_intelligence.jazzer.autofuzz;
+
+import static com.code_intelligence.jazzer.autofuzz.TestHelpers.consumeTestCase;
+
+import com.code_intelligence.jazzer.autofuzz.testdata.EmployeeWithSetters;
+import java.util.Arrays;
+import org.junit.Test;
+
+public class SettersTest {
+ @Test
+ public void testEmptyConstructorWithSetters() {
+ EmployeeWithSetters employee = new EmployeeWithSetters();
+ employee.setFirstName("foo");
+ employee.setAge(26);
+
+ consumeTestCase(employee,
+ "((java.util.function.Supplier<com.code_intelligence.jazzer.autofuzz.testdata.EmployeeWithSetters>) (() -> {com.code_intelligence.jazzer.autofuzz.testdata.EmployeeWithSetters autofuzzVariable0 = new com.code_intelligence.jazzer.autofuzz.testdata.EmployeeWithSetters(); autofuzzVariable0.setFirstName(\"foo\"); autofuzzVariable0.setAge(26); return autofuzzVariable0;})).get()",
+ Arrays.asList((byte) 1, // do not return null for EmployeeWithSetters
+ 0, // pick first constructor
+ 2, // pick two setters
+ 1, // pick second setter
+ 0, // pick first setter
+ (byte) 1, // do not return null for String
+ 6, // remaining bytes
+ "foo", // setFirstName
+ 26 // setAge
+ ));
+ }
+}
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/TestHelpers.java b/src/test/java/com/code_intelligence/jazzer/autofuzz/TestHelpers.java
new file mode 100644
index 00000000..89f9c968
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/TestHelpers.java
@@ -0,0 +1,85 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.code_intelligence.jazzer.autofuzz;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import com.code_intelligence.jazzer.api.CannedFuzzedDataProvider;
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.List;
+
+class TestHelpers {
+ static void assertGeneralEquals(Object expected, Object actual) {
+ Class<?> type = expected != null ? expected.getClass() : Object.class;
+ if (type.isArray()) {
+ if (type.getComponentType() == boolean.class) {
+ assertArrayEquals((boolean[]) expected, (boolean[]) actual);
+ } else if (type.getComponentType() == char.class) {
+ assertArrayEquals((char[]) expected, (char[]) actual);
+ } else if (type.getComponentType() == short.class) {
+ assertArrayEquals((short[]) expected, (short[]) actual);
+ } else if (type.getComponentType() == long.class) {
+ assertArrayEquals((long[]) expected, (long[]) actual);
+ } else {
+ assertArrayEquals((Object[]) expected, (Object[]) actual);
+ }
+ } else if (type == ByteArrayInputStream.class) {
+ ByteArrayInputStream expectedStream = (ByteArrayInputStream) expected;
+ ByteArrayInputStream actualStream = (ByteArrayInputStream) actual;
+ assertArrayEquals(readAllBytes(expectedStream), readAllBytes(actualStream));
+ } else {
+ assertEquals(expected, actual);
+ }
+ }
+
+ static void consumeTestCase(
+ Object expectedResult, String expectedResultString, List<Object> cannedData) {
+ Class<?> type = expectedResult != null ? expectedResult.getClass() : Object.class;
+ consumeTestCase(type, expectedResult, expectedResultString, cannedData);
+ }
+
+ static void consumeTestCase(
+ Type type, Object expectedResult, String expectedResultString, List<Object> cannedData) {
+ AutofuzzCodegenVisitor visitor = new AutofuzzCodegenVisitor();
+ FuzzedDataProvider data = CannedFuzzedDataProvider.create(cannedData);
+ assertGeneralEquals(expectedResult, new Meta(null).consume(data, type, visitor));
+ assertEquals(expectedResultString, visitor.generate());
+ }
+
+ static void autofuzzTestCase(Object expectedResult, String expectedResultString, Executable func,
+ List<Object> cannedData) {
+ AutofuzzCodegenVisitor visitor = new AutofuzzCodegenVisitor();
+ FuzzedDataProvider data = CannedFuzzedDataProvider.create(cannedData);
+ if (func instanceof Method) {
+ assertGeneralEquals(expectedResult, new Meta(null).autofuzz(data, (Method) func, visitor));
+ } else {
+ assertGeneralEquals(
+ expectedResult, new Meta(null).autofuzz(data, (Constructor<?>) func, visitor));
+ }
+ assertEquals(expectedResultString, visitor.generate());
+ }
+
+ private static byte[] readAllBytes(ByteArrayInputStream in) {
+ byte[] result = new byte[in.available()];
+ in.read(result, 0, in.available());
+ return result;
+ }
+}
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/testdata/BUILD.bazel b/src/test/java/com/code_intelligence/jazzer/autofuzz/testdata/BUILD.bazel
new file mode 100644
index 00000000..c2c68803
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/testdata/BUILD.bazel
@@ -0,0 +1,5 @@
+java_library(
+ name = "test_data",
+ srcs = glob(["*.java"]),
+ visibility = ["//visibility:public"],
+)
diff --git a/src/test/java/com/code_intelligence/jazzer/autofuzz/testdata/EmployeeWithSetters.java b/src/test/java/com/code_intelligence/jazzer/autofuzz/testdata/EmployeeWithSetters.java
new file mode 100644
index 00000000..2c76a61f
--- /dev/null
+++ b/src/test/java/com/code_intelligence/jazzer/autofuzz/testdata/EmployeeWithSetters.java
@@ -0,0 +1,56 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.code_intelligence.jazzer.autofuzz.testdata;
+
+import java.util.Objects;
+
+public class EmployeeWithSetters {
+ private String firstName;
+ private String lastName;
+ private String jobTitle;
+ private int age;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ EmployeeWithSetters hero = (EmployeeWithSetters) o;
+ return age == hero.age && Objects.equals(firstName, hero.firstName)
+ && Objects.equals(lastName, hero.lastName) && Objects.equals(jobTitle, hero.jobTitle);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(firstName, lastName, jobTitle, age);
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public void setJobTitle(String jobTitle) {
+ this.jobTitle = jobTitle;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+}