diff --git a/WORKSPACE b/WORKSPACE index 5498f5022..caa501b0e 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -17,7 +17,18 @@ workspace(name = "com_google_fuzztest") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") ################################################################################ -# Transitive dependencies (not directly required by FuzzTest itself) +# Direct dependencies required by core FuzzTest (//fuzztest:fuzztest_core) +################################################################################ + +http_archive( + name = "com_google_absl", + sha256 = "0ddd37f347c58d89f449dd189a645bfd97bcd85c5284404a3af27a3ca3476f39", + strip_prefix = "abseil-cpp-fad946221cec37175e762c399760f54b9de9a9fa", + url = "https://github.com/abseil/abseil-cpp/archive/fad946221cec37175e762c399760f54b9de9a9fa.tar.gz", +) + +################################################################################ +# Transitive dependencies for core FuzzTest ################################################################################ # Required by com_google_absl. @@ -31,16 +42,9 @@ http_archive( ) ################################################################################ -# Direct dependencies +# Direct dependencies required for full FuzzTest (//fuzztest:fuzztest) ################################################################################ -http_archive( - name = "com_google_absl", - sha256 = "0ddd37f347c58d89f449dd189a645bfd97bcd85c5284404a3af27a3ca3476f39", - strip_prefix = "abseil-cpp-fad946221cec37175e762c399760f54b9de9a9fa", - url = "https://github.com/abseil/abseil-cpp/archive/fad946221cec37175e762c399760f54b9de9a9fa.tar.gz", -) - http_archive( name = "com_googlesource_code_re2", sha256 = "5bb6875ae1cd1e9fedde98018c346db7260655f86fdb8837e3075103acd3649b", @@ -63,7 +67,7 @@ http_archive( ) ################################################################################ -# Dependencies required for Riegeli +# Transitive dependencies required by Riegeli (and therefore by full FuzzTest) ################################################################################ http_archive( diff --git a/cmake/AddFuzzTest.cmake b/cmake/AddFuzzTest.cmake index 8b7b323cc..7f679120b 100644 --- a/cmake/AddFuzzTest.cmake +++ b/cmake/AddFuzzTest.cmake @@ -1,5 +1,4 @@ -function(link_fuzztest name) - target_link_libraries(${name} PRIVATE fuzztest::fuzztest_gtest_main) +function(_link_fuzztest_compatibility_mode name) if (FUZZTEST_COMPATIBILITY_MODE STREQUAL "libfuzzer") EXECUTE_PROCESS ( COMMAND bash -c "command -v llvm-config || command -v llvm-config-16 || command -v llvm-config-15 || command -v llvm-config-14 || command -v llvm-config-13 || command -v llvm-config-12 || echo" @@ -12,3 +11,23 @@ function(link_fuzztest name) target_link_libraries(${name} PRIVATE ${FUZZER_NO_MAIN}) endif () endfunction() + +function(link_fuzztest name) + target_link_libraries( + ${name} + PRIVATE + fuzztest::fuzztest + fuzztest::fuzztest_gtest_main + ) + _link_fuzztest_compatibility_mode(${name}) +endfunction() + +function(link_fuzztest_core name) + target_link_libraries( + ${name} + PRIVATE + fuzztest::fuzztest_core + fuzztest::fuzztest_gtest_main + ) + _link_fuzztest_compatibility_mode(${name}) +endfunction() diff --git a/domain_tests/BUILD b/domain_tests/BUILD index d23ba2382..aaf19287c 100644 --- a/domain_tests/BUILD +++ b/domain_tests/BUILD @@ -28,7 +28,7 @@ cc_test( "@com_google_absl//absl/types:optional", "@com_google_absl//absl/types:span", "@com_google_absl//absl/types:variant", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_googletest//:gtest_main", ], ) @@ -60,7 +60,6 @@ cc_test( "@com_google_absl//absl/status", "@com_google_absl//absl/time", "@com_google_fuzztest//fuzztest:absl_helpers", - "@com_google_fuzztest//fuzztest:domain", "@com_google_fuzztest//fuzztest:domain_core", "@com_google_fuzztest//fuzztest:serialization", "@com_google_fuzztest//fuzztest:test_protobuf_cc_proto", @@ -78,7 +77,7 @@ cc_test( "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/random", "@com_google_absl//absl/strings", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_fuzztest//fuzztest:type_support", "@com_google_googletest//:gtest_main", ], @@ -93,7 +92,7 @@ cc_test( "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/random", "@com_google_fuzztest//fuzztest:coverage", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_fuzztest//fuzztest:type_support", "@com_google_googletest//:gtest_main", ], @@ -173,7 +172,7 @@ cc_test( "@com_google_absl//absl/numeric:int128", "@com_google_absl//absl/random", "@com_google_absl//absl/types:span", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_fuzztest//fuzztest:meta", "@com_google_fuzztest//fuzztest:type_support", "@com_google_googletest//:gtest_main", @@ -191,7 +190,7 @@ cc_test( "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_fuzztest//fuzztest:serialization", "@com_google_googletest//:gtest_main", ], @@ -203,7 +202,7 @@ cc_test( deps = [ ":domain_testing", "@com_google_absl//absl/random", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_googletest//:gtest_main", ], ) @@ -214,7 +213,7 @@ cc_test( deps = [ ":domain_testing", "@com_google_absl//absl/random", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_googletest//:gtest_main", ], ) @@ -228,7 +227,7 @@ cc_test( "@com_google_absl//absl/random", "@com_google_absl//absl/time", "@com_google_absl//absl/types:span", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_googletest//:gtest_main", ], ) @@ -240,7 +239,7 @@ cc_test( ":domain_testing", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/random", - "@com_google_fuzztest//fuzztest:domain", + "@com_google_fuzztest//fuzztest:domain_core", "@com_google_googletest//:gtest_main", ], ) diff --git a/domain_tests/CMakeLists.txt b/domain_tests/CMakeLists.txt index 1d61eb064..efa6cc9db 100644 --- a/domain_tests/CMakeLists.txt +++ b/domain_tests/CMakeLists.txt @@ -15,7 +15,7 @@ fuzztest_cc_test( absl::optional absl::span absl::variant - fuzztest::domain + fuzztest::domain_core GTest::gmock_main ) @@ -48,7 +48,6 @@ fuzztest_cc_test( absl::status absl::time fuzztest::absl_helpers - fuzztest::domain fuzztest::domain_core fuzztest::serialization test_protobuf @@ -67,7 +66,7 @@ fuzztest_cc_test( absl::flat_hash_set absl::random_random absl::strings - fuzztest::domain + fuzztest::domain_core fuzztest::type_support GTest::gmock_main ) @@ -83,7 +82,7 @@ fuzztest_cc_test( absl::flat_hash_set absl::random_random fuzztest::coverage - fuzztest::domain + fuzztest::domain_core fuzztest::type_support GTest::gmock_main ) @@ -166,7 +165,7 @@ fuzztest_cc_test( absl::int128 absl::random_random absl::span - fuzztest::domain + fuzztest::domain_core fuzztest::meta fuzztest::type_support GTest::gmock_main @@ -185,7 +184,7 @@ fuzztest_cc_test( absl::status absl::strings absl::span - fuzztest::domain + fuzztest::domain_core fuzztest::serialization GTest::gmock_main ) @@ -198,7 +197,7 @@ fuzztest_cc_test( DEPS fuzztest::domain_testing absl::random_random - fuzztest::domain + fuzztest::domain_core GTest::gmock_main ) @@ -210,7 +209,7 @@ fuzztest_cc_test( DEPS fuzztest::domain_testing absl::random_random - fuzztest::domain + fuzztest::domain_core GTest::gmock_main ) @@ -225,7 +224,7 @@ fuzztest_cc_test( absl::random_random absl::time absl::span - fuzztest::domain + fuzztest::domain_core GTest::gmock_main ) @@ -238,6 +237,6 @@ fuzztest_cc_test( fuzztest::domain_testing absl::flat_hash_set absl::random_random - fuzztest::domain + fuzztest::domain_core GTest::gmock_main ) diff --git a/domain_tests/aggregate_combinators_test.cc b/domain_tests/aggregate_combinators_test.cc index f6cca1a16..a99d55816 100644 --- a/domain_tests/aggregate_combinators_test.cc +++ b/domain_tests/aggregate_combinators_test.cc @@ -28,7 +28,7 @@ #include "absl/types/optional.h" #include "absl/types/span.h" #include "absl/types/variant.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" namespace fuzztest { diff --git a/domain_tests/arbitrary_domains_test.cc b/domain_tests/arbitrary_domains_test.cc index db6370e9e..821b87cd6 100644 --- a/domain_tests/arbitrary_domains_test.cc +++ b/domain_tests/arbitrary_domains_test.cc @@ -35,7 +35,7 @@ #include "absl/random/random.h" #include "absl/status/status.h" #include "absl/time/time.h" -#include "./fuzztest/domain.h" // IWYU pragma: keep +#include "./fuzztest/domain_core.h" // IWYU pragma: keep #include "./domain_tests/domain_testing.h" #include "./fuzztest/internal/domains/absl_helpers.h" #include "./fuzztest/internal/domains/arbitrary_impl.h" diff --git a/domain_tests/container_combinators_test.cc b/domain_tests/container_combinators_test.cc index 193bab5dd..92268872e 100644 --- a/domain_tests/container_combinators_test.cc +++ b/domain_tests/container_combinators_test.cc @@ -33,7 +33,7 @@ #include "absl/container/flat_hash_set.h" #include "absl/random/random.h" #include "absl/strings/str_cat.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" #include "./fuzztest/internal/type_support.h" diff --git a/domain_tests/container_test.cc b/domain_tests/container_test.cc index a2c5d4517..6336ba8a7 100644 --- a/domain_tests/container_test.cc +++ b/domain_tests/container_test.cc @@ -32,7 +32,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/random/random.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" #include "./fuzztest/internal/coverage.h" #include "./fuzztest/internal/type_support.h" diff --git a/domain_tests/misc_domains_test.cc b/domain_tests/misc_domains_test.cc index 0bfaac75d..531d1fc9d 100644 --- a/domain_tests/misc_domains_test.cc +++ b/domain_tests/misc_domains_test.cc @@ -27,7 +27,7 @@ #include "absl/numeric/int128.h" #include "absl/random/random.h" #include "absl/types/span.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" #include "./fuzztest/internal/meta.h" #include "./fuzztest/internal/type_support.h" diff --git a/domain_tests/numeric_domains_test.cc b/domain_tests/numeric_domains_test.cc index 7853f55e6..57d6d5050 100644 --- a/domain_tests/numeric_domains_test.cc +++ b/domain_tests/numeric_domains_test.cc @@ -33,7 +33,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/substitute.h" #include "absl/types/span.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" #include "./fuzztest/internal/serialization.h" diff --git a/domain_tests/pointer_domains_test.cc b/domain_tests/pointer_domains_test.cc index 717328628..9330bcd7b 100644 --- a/domain_tests/pointer_domains_test.cc +++ b/domain_tests/pointer_domains_test.cc @@ -21,7 +21,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/random/random.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" namespace fuzztest { diff --git a/domain_tests/recursive_domains_test.cc b/domain_tests/recursive_domains_test.cc index 8294a2297..e9072884c 100644 --- a/domain_tests/recursive_domains_test.cc +++ b/domain_tests/recursive_domains_test.cc @@ -30,7 +30,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/random/random.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" namespace fuzztest { diff --git a/domain_tests/specific_value_domains_test.cc b/domain_tests/specific_value_domains_test.cc index 2f4e789bf..215a6f987 100644 --- a/domain_tests/specific_value_domains_test.cc +++ b/domain_tests/specific_value_domains_test.cc @@ -24,7 +24,7 @@ #include "absl/random/random.h" #include "absl/time/time.h" #include "absl/types/span.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" namespace fuzztest { diff --git a/domain_tests/string_domains_test.cc b/domain_tests/string_domains_test.cc index 083e3ef1f..057b03719 100644 --- a/domain_tests/string_domains_test.cc +++ b/domain_tests/string_domains_test.cc @@ -25,7 +25,7 @@ #include "gtest/gtest.h" #include "absl/container/flat_hash_set.h" #include "absl/random/random.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./domain_tests/domain_testing.h" namespace fuzztest { diff --git a/e2e_tests/testdata/BUILD b/e2e_tests/testdata/BUILD index b59efa2f6..e27baffda 100644 --- a/e2e_tests/testdata/BUILD +++ b/e2e_tests/testdata/BUILD @@ -75,7 +75,7 @@ cc_binary( testonly = 1, srcs = ["fuzz_tests_with_invalid_seeds.cc"], deps = [ - "@com_google_fuzztest//fuzztest", + "@com_google_fuzztest//fuzztest:fuzztest_core", "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", ], ) @@ -85,7 +85,7 @@ cc_binary( testonly = 1, srcs = ["dynamically_registered_fuzz_tests.cc"], deps = [ - "@com_google_fuzztest//fuzztest", + "@com_google_fuzztest//fuzztest:fuzztest_core", "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", ], ) diff --git a/e2e_tests/testdata/dynamically_registered_fuzz_tests.cc b/e2e_tests/testdata/dynamically_registered_fuzz_tests.cc index 8d4591d9f..e86aec681 100644 --- a/e2e_tests/testdata/dynamically_registered_fuzz_tests.cc +++ b/e2e_tests/testdata/dynamically_registered_fuzz_tests.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "./fuzztest/fuzztest.h" +#include "./fuzztest/fuzztest_core.h" namespace { diff --git a/e2e_tests/testdata/fuzz_tests_with_invalid_seeds.cc b/e2e_tests/testdata/fuzz_tests_with_invalid_seeds.cc index 2596ea150..37b836e98 100644 --- a/e2e_tests/testdata/fuzz_tests_with_invalid_seeds.cc +++ b/e2e_tests/testdata/fuzz_tests_with_invalid_seeds.cc @@ -14,7 +14,7 @@ // Fuzz test examples to be used by `functional_test` only. -#include "./fuzztest/fuzztest.h" +#include "./fuzztest/fuzztest_core.h" namespace { diff --git a/fuzztest/BUILD b/fuzztest/BUILD index e11ea2c4e..7f4bab2fb 100644 --- a/fuzztest/BUILD +++ b/fuzztest/BUILD @@ -39,10 +39,28 @@ config_setting( cc_library( name = "fuzztest", - srcs = ["fuzztest.cc"], hdrs = ["fuzztest.h"], deps = [ ":domain", + ":fuzztest_macros", + ], +) + +cc_library( + name = "fuzztest_core", + hdrs = ["fuzztest_core.h"], + deps = [ + ":domain_core", + ":fuzztest_macros", + ], +) + +cc_library( + name = "fuzztest_macros", + hdrs = [ + "fuzztest_macros.h", + ], + deps = [ ":io", ":registration", ":registry", @@ -319,7 +337,6 @@ cc_library( hdrs = ["internal/fixture_driver.h"], deps = [ ":any", - ":domain", ":domain_core", ":logging", ":registration", @@ -392,7 +409,7 @@ cc_test( name = "io_test", srcs = ["internal/io_test.cc"], deps = [ - ":fuzztest", + ":fuzztest_core", ":io", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", @@ -432,7 +449,6 @@ cc_library( name = "registration", hdrs = ["internal/registration.h"], deps = [ - ":domain", ":domain_core", ":meta", ":type_support", @@ -467,7 +483,6 @@ cc_library( deps = [ ":configuration", ":coverage", - ":domain", ":domain_core", ":fixture_driver", ":flag_name", @@ -495,7 +510,7 @@ cc_test( name = "runtime_test", srcs = ["internal/runtime_test.cc"], deps = [ - ":domain", + ":domain_core", ":runtime", ":test_protobuf_cc_proto", "@com_google_absl//absl/time", @@ -599,7 +614,6 @@ cc_test( name = "table_of_recent_compares_test", srcs = ["internal/table_of_recent_compares_test.cc"], deps = [ - ":domain", ":table_of_recent_compares", "@com_google_absl//absl/random", "@com_google_googletest//:gtest_main", diff --git a/fuzztest/CMakeLists.txt b/fuzztest/CMakeLists.txt index 7438df7e8..a2016be61 100644 --- a/fuzztest/CMakeLists.txt +++ b/fuzztest/CMakeLists.txt @@ -11,10 +11,27 @@ fuzztest_cc_library( fuzztest HDRS "fuzztest.h" - SRCS - "fuzztest.cc" DEPS fuzztest::domain + fuzztest::fuzztest_macros +) + +fuzztest_cc_library( + NAME + fuzztest_core + HDRS + "fuzztest_core.h" + DEPS + fuzztest::domain_core + fuzztest::fuzztest_macros +) + +fuzztest_cc_library( + NAME + fuzztest_macros + HDRS + "fuzztest_macros.h" + DEPS fuzztest::io fuzztest::registration fuzztest::registry @@ -253,7 +270,6 @@ fuzztest_cc_library( "internal/fixture_driver.cc" DEPS fuzztest::any - fuzztest::domain fuzztest::domain_core fuzztest::logging fuzztest::registration @@ -324,7 +340,7 @@ fuzztest_cc_test( SRCS "internal/io_test.cc" DEPS - fuzztest::fuzztest + fuzztest::fuzztest_core fuzztest::io absl::strings GTest::gmock_main @@ -371,7 +387,6 @@ fuzztest_cc_library( HDRS "internal/registration.h" DEPS - fuzztest::domain fuzztest::domain_core fuzztest::meta fuzztest::type_support @@ -407,7 +422,6 @@ fuzztest_cc_library( DEPS fuzztest::configuration fuzztest::coverage - fuzztest::domain fuzztest::domain_core fuzztest::fixture_driver fuzztest::io @@ -435,7 +449,7 @@ fuzztest_cc_test( SRCS "internal/runtime_test.cc" DEPS - fuzztest::domain + fuzztest::domain_core fuzztest::runtime test_protobuf absl::time @@ -552,7 +566,6 @@ fuzztest_cc_test( SRCS "internal/table_of_recent_compares_test.cc" DEPS - fuzztest::domain fuzztest::table_of_recent_compares absl::random_random GTest::gmock_main diff --git a/fuzztest/fuzztest.cc b/fuzztest/fuzztest.cc deleted file mode 100644 index b68ead141..000000000 --- a/fuzztest/fuzztest.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2022 Google LLC -// -// 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. - -#include "./fuzztest/fuzztest.h" - -#include -#include -#include -#include - -#include "./fuzztest/internal/io.h" - -namespace fuzztest { - -std::vector> ReadFilesFromDirectory( - std::string_view dir) { - std::vector files = - internal::ReadFileOrDirectory({dir.data(), dir.size()}); - - std::vector> out; - out.reserve(files.size()); - - for (const internal::FilePathAndData& file : files) { - out.push_back(std::make_tuple(file.data)); - } - - return out; -} - -} // namespace fuzztest diff --git a/fuzztest/fuzztest.h b/fuzztest/fuzztest.h index 3faae1405..a153e36e1 100644 --- a/fuzztest/fuzztest.h +++ b/fuzztest/fuzztest.h @@ -15,115 +15,9 @@ #ifndef FUZZTEST_FUZZTEST_FUZZTEST_H_ #define FUZZTEST_FUZZTEST_FUZZTEST_H_ -#include -#include -#include -#include - // IWYU pragma: begin_exports #include "./fuzztest/domain.h" -#include "./fuzztest/internal/registration.h" -#include "./fuzztest/internal/registry.h" +#include "./fuzztest/fuzztest_macros.h" // IWYU pragma: end_exports -namespace fuzztest { - -// The FUZZ_TEST macro registers a fuzz test. -// -// Fuzz tests are parameterized unit tests, also called property-based tests. -// The tested property is captured by a function with some parameters, and the -// input domains of the parameters can be specified with the FUZZ_TEST macro -// that registers and instantiates the test: -// -// void CallingMyApiNeverCrashes(int x, const std::string& s) { -// bool result = MyApi(x, s); // This function call should never crash. -// ASSERT_TRUE(result); // Can have explicit assertions too. -// } -// FUZZ_TEST(MySuite, CallingMyApiNeverCrashes) -// .WithDomains(/*x:*/fuzztest::InRange(0,10), -// /*s:*/fuzztest::AsciiString()) -// .WithSeeds({{5, "Foo"}, {10, "Bar"}}); -// -// where `MySuite` is an identifier for a group of related tests, and -// `CallingMyApiNeverCrashes` is the name of the test and also the name of the -// "property function". The property function can have any number of parameters. -// The input domain of each parameter can be assigned using `.WithDomains()`, -// and the initial seed values can be provided using `.WithSeeds()`. -// -// When each parameter's input domain is `Arbitrary()`, which allows any -// value of a given type T, i.e.: -// -// FUZZ_TEST(MySuite, CallingMyApiNeverCrashes) -// .WithDomains(/*x:*/fuzztest::Arbitrary(), -// /*s:*/fuzztest::Arbitrary()); -// -// then the input domain assignment with `.WithDomains()` can be omitted: -// -// FUZZ_TEST(MySuite, CallingMyApiNeverCrashes); -// -// Note: When specifying both the domains and seeds, the domain clause has to -// be specified first. -#define FUZZ_TEST(suite_name, func) INTERNAL_FUZZ_TEST(suite_name, func) - -// The FUZZ_TEST_F macro registers a fuzz test that uses a test fixture. -// -// The first parameter is the name of the fixture class, which is also used as -// the name of the test suite. The second parameter is the name of the property -// function (also used as the test name), which must be defined as a public -// member of the fixture class. -// -// A test fixture can be any default-constructible class. The fixture's setup -// code should be in its constructor, and the teardown code should be in its -// destructor. While running the fuzz test, which involves calling the property -// function multiple times with various inputs, the fixture will be instantiated -// only once at the beginning and destroyed at the end of the fuzz test. In -// particular, the same instance will be used in all calls to the property -// function. -// -// If the fixture you are using is a GoogleTest fixture (i.e., it extends -// `::testing::Test`, either directly or indirectly), then you will additionally -// need to wrap the fixture in an adapter. For more details, see -// https://github.com/google/fuzztest/blob/main/doc/fixtures.md. -// -// Just like the FUZZ_TEST macro, the FUZZ_TEST_F macro allows specifying the -// domains and seeds using the `.WithDomains()` and `.WithSeeds()` clauses. -// -// Example: -// -// class FooFuzzTest { -// public: -// FooFuzzTest() { foo_.SetUp(); } -// ~FooFuzzTest() { foo_.TearDown(); } -// -// void CallingFooBarNeverCrashes(int x, const std::string& s) { -// bool result = foo_.Bar(x, s); -// ASSERT_TRUE(result); -// } -// -// private: -// Foo foo_; -// }; -// FUZZ_TEST_F(FooFuzzTest, CallingFooBarNeverCrashes) -// .WithDomains(/*x:*/fuzztest::Positive(), -// /*s:*/fuzztest::AsciiString()) -// .WithSeeds({{5, "Foo"}, {10, "Bar"}}); -// -#define FUZZ_TEST_F(fixture, func) \ - INTERNAL_FUZZ_TEST_F(fixture, func, fixture, func) - -// Reads files as strings from the directory `dir` and returns a vector usable -// by .WithSeeds(). -// -// Example: -// -// void MyThingNeverCrashes(const std::string& s) { -// DoThingsWith(s); -// } -// FUZZ_TEST(MySuite, MyThingNeverCrashes) -// .WithSeeds(ReadFilesFromDirectory(kCorpusPath)); -std::vector> ReadFilesFromDirectory( - std::string_view dir); - -} // namespace fuzztest - #endif // FUZZTEST_FUZZTEST_FUZZTEST_H_ diff --git a/fuzztest/fuzztest_core.h b/fuzztest/fuzztest_core.h new file mode 100644 index 000000000..23cd116f1 --- /dev/null +++ b/fuzztest/fuzztest_core.h @@ -0,0 +1,23 @@ +// Copyright 2023 Google LLC +// +// 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. + +#ifndef FUZZTEST_FUZZTEST_FUZZTEST_CORE_H_ +#define FUZZTEST_FUZZTEST_FUZZTEST_CORE_H_ + +// IWYU pragma: begin_exports +#include "./fuzztest/domain_core.h" +#include "./fuzztest/fuzztest_macros.h" +// IWYU pragma: end_exports + +#endif // FUZZTEST_FUZZTEST_FUZZTEST_CORE_H_ diff --git a/fuzztest/fuzztest_macros.h b/fuzztest/fuzztest_macros.h new file mode 100644 index 000000000..6228e2fbc --- /dev/null +++ b/fuzztest/fuzztest_macros.h @@ -0,0 +1,131 @@ +// Copyright 2022 Google LLC +// +// 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. + +#ifndef FUZZTEST_FUZZTEST_FUZZTEST_MACROS_H_ +#define FUZZTEST_FUZZTEST_FUZZTEST_MACROS_H_ + +#include +#include +#include +#include + +// IWYU pragma: begin_exports +#include "./fuzztest/internal/io.h" +#include "./fuzztest/internal/registration.h" +#include "./fuzztest/internal/registry.h" +// IWYU pragma: end_exports + +namespace fuzztest { + +// The FUZZ_TEST macro registers a fuzz test. +// +// Fuzz tests are parameterized unit tests, also called property-based tests. +// The tested property is captured by a function with some parameters, and the +// input domains of the parameters can be specified with the FUZZ_TEST macro +// that registers and instantiates the test: +// +// void CallingMyApiNeverCrashes(int x, const std::string& s) { +// bool result = MyApi(x, s); // This function call should never crash. +// ASSERT_TRUE(result); // Can have explicit assertions too. +// } +// FUZZ_TEST(MySuite, CallingMyApiNeverCrashes) +// .WithDomains(/*x:*/fuzztest::InRange(0,10), +// /*s:*/fuzztest::AsciiString()) +// .WithSeeds({{5, "Foo"}, {10, "Bar"}}); +// +// where `MySuite` is an identifier for a group of related tests, and +// `CallingMyApiNeverCrashes` is the name of the test and also the name of the +// "property function". The property function can have any number of parameters. +// The input domain of each parameter can be assigned using `.WithDomains()`, +// and the initial seed values can be provided using `.WithSeeds()`. +// +// When each parameter's input domain is `Arbitrary()`, which allows any +// value of a given type T, i.e.: +// +// FUZZ_TEST(MySuite, CallingMyApiNeverCrashes) +// .WithDomains(/*x:*/fuzztest::Arbitrary(), +// /*s:*/fuzztest::Arbitrary()); +// +// then the input domain assignment with `.WithDomains()` can be omitted: +// +// FUZZ_TEST(MySuite, CallingMyApiNeverCrashes); +// +// Note: When specifying both the domains and seeds, the domain clause has to +// be specified first. +#define FUZZ_TEST(suite_name, func) INTERNAL_FUZZ_TEST(suite_name, func) + +// The FUZZ_TEST_F macro registers a fuzz test that uses a test fixture. +// +// The first parameter is the name of the fixture class, which is also used as +// the name of the test suite. The second parameter is the name of the property +// function (also used as the test name), which must be defined as a public +// member of the fixture class. +// +// A test fixture can be any default-constructible class. The fixture's setup +// code should be in its constructor, and the teardown code should be in its +// destructor. While running the fuzz test, which involves calling the property +// function multiple times with various inputs, the fixture will be instantiated +// only once at the beginning and destroyed at the end of the fuzz test. In +// particular, the same instance will be used in all calls to the property +// function. +// +// If the fixture you are using is a GoogleTest fixture (i.e., it extends +// `::testing::Test`, either directly or indirectly), then you will additionally +// need to wrap the fixture in an adapter. For more details, see +// https://github.com/google/fuzztest/blob/main/doc/fixtures.md. +// +// Just like the FUZZ_TEST macro, the FUZZ_TEST_F macro allows specifying the +// domains and seeds using the `.WithDomains()` and `.WithSeeds()` clauses. +// +// Example: +// +// class FooFuzzTest { +// public: +// FooFuzzTest() { foo_.SetUp(); } +// ~FooFuzzTest() { foo_.TearDown(); } +// +// void CallingFooBarNeverCrashes(int x, const std::string& s) { +// bool result = foo_.Bar(x, s); +// ASSERT_TRUE(result); +// } +// +// private: +// Foo foo_; +// }; +// FUZZ_TEST_F(FooFuzzTest, CallingFooBarNeverCrashes) +// .WithDomains(/*x:*/fuzztest::Positive(), +// /*s:*/fuzztest::AsciiString()) +// .WithSeeds({{5, "Foo"}, {10, "Bar"}}); +// +#define FUZZ_TEST_F(fixture, func) \ + INTERNAL_FUZZ_TEST_F(fixture, func, fixture, func) + +// Reads files as strings from the directory `dir` and returns a vector usable +// by .WithSeeds(). +// +// Example: +// +// void MyThingNeverCrashes(const std::string& s) { +// DoThingsWith(s); +// } +// FUZZ_TEST(MySuite, MyThingNeverCrashes) +// .WithSeeds(ReadFilesFromDirectory(kCorpusPath)); +inline std::vector> ReadFilesFromDirectory( + std::string_view dir) { + return internal::ReadFilesFromDirectory({dir.data(), dir.size()}); +} + +} // namespace fuzztest + +#endif // FUZZTEST_FUZZTEST_FUZZTEST_MACROS_H_ diff --git a/fuzztest/internal/io.cc b/fuzztest/internal/io.cc index f3e4af756..9723d6dc4 100644 --- a/fuzztest/internal/io.cc +++ b/fuzztest/internal/io.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -152,4 +153,19 @@ absl::string_view Basename(absl::string_view filename) { : filename.substr(last_slash_pos + 1); } +std::vector> ReadFilesFromDirectory( + std::string_view dir) { + std::vector files = + ReadFileOrDirectory({dir.data(), dir.size()}); + + std::vector> out; + out.reserve(files.size()); + + for (const FilePathAndData& file : files) { + out.push_back(std::make_tuple(file.data)); + } + + return out; +} + } // namespace fuzztest::internal diff --git a/fuzztest/internal/io.h b/fuzztest/internal/io.h index 10668757d..b2f4d9e8d 100644 --- a/fuzztest/internal/io.h +++ b/fuzztest/internal/io.h @@ -50,6 +50,11 @@ std::vector ListDirectory(absl::string_view dir); // Returns the basename of `filename`. absl::string_view Basename(absl::string_view filename); +// Reads files as strings from the directory `dir` and returns a vector usable +// by .WithSeeds(). +std::vector> ReadFilesFromDirectory( + absl::string_view dir); + } // namespace fuzztest::internal #endif // FUZZTEST_FUZZTEST_INTERNAL_IO_H_ diff --git a/fuzztest/internal/io_test.cc b/fuzztest/internal/io_test.cc index 98841f138..5b9818b8c 100644 --- a/fuzztest/internal/io_test.cc +++ b/fuzztest/internal/io_test.cc @@ -28,7 +28,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_cat.h" -#include "./fuzztest/fuzztest.h" +#include "./fuzztest/fuzztest_core.h" namespace fuzztest::internal { namespace { diff --git a/fuzztest/internal/registration.h b/fuzztest/internal/registration.h index 62a8c2f60..351b8852f 100644 --- a/fuzztest/internal/registration.h +++ b/fuzztest/internal/registration.h @@ -28,7 +28,7 @@ #include "absl/functional/any_invocable.h" #include "absl/strings/str_format.h" #include "absl/types/span.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./fuzztest/internal/domains/aggregate_of_impl.h" #include "./fuzztest/internal/domains/domain_base.h" #include "./fuzztest/internal/meta.h" diff --git a/fuzztest/internal/runtime.h b/fuzztest/internal/runtime.h index 541ffb0e1..3149f7b2f 100644 --- a/fuzztest/internal/runtime.h +++ b/fuzztest/internal/runtime.h @@ -37,7 +37,7 @@ #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "absl/types/span.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./fuzztest/internal/configuration.h" #include "./fuzztest/internal/coverage.h" #include "./fuzztest/internal/fixture_driver.h" diff --git a/fuzztest/internal/runtime_test.cc b/fuzztest/internal/runtime_test.cc index 0fbbad947..e8e0a8e92 100644 --- a/fuzztest/internal/runtime_test.cc +++ b/fuzztest/internal/runtime_test.cc @@ -20,7 +20,7 @@ #include "gtest/gtest.h" #include "absl/time/time.h" -#include "./fuzztest/domain.h" +#include "./fuzztest/domain_core.h" #include "./fuzztest/internal/test_protobuf.pb.h" namespace fuzztest::internal {