Run only fuzz tests in fuzzing mode when no test or test filter is specified. PiperOrigin-RevId: 633330603
diff --git a/e2e_tests/BUILD b/e2e_tests/BUILD index 31631e2..868ac5f 100644 --- a/e2e_tests/BUILD +++ b/e2e_tests/BUILD
@@ -31,6 +31,7 @@ "@com_google_fuzztest//e2e_tests/testdata:dynamically_registered_fuzz_tests.stripped", "@com_google_fuzztest//e2e_tests/testdata:fuzz_tests_for_functional_testing.stripped", "@com_google_fuzztest//e2e_tests/testdata:fuzz_tests_with_invalid_seeds.stripped", + "@com_google_fuzztest//e2e_tests/testdata:unit_test_and_fuzz_tests.stripped", ], defines = select({ "@com_google_fuzztest//fuzztest:use_centipede": ["FUZZTEST_USE_CENTIPEDE"],
diff --git a/e2e_tests/functional_test.cc b/e2e_tests/functional_test.cc index 2875444..39d317c 100644 --- a/e2e_tests/functional_test.cc +++ b/e2e_tests/functional_test.cc
@@ -17,7 +17,7 @@ #include <cstdint> #include <cstdio> #include <cstdlib> -#include <filesystem> +#include <filesystem> // NOLINT #include <optional> #include <string> #include <tuple> @@ -1135,6 +1135,37 @@ EXPECT_THAT(status, Eq(Signal(SIGABRT))); } +// TODO: b/340232436 - Once fixed, remove this test since we will no longer need +// to restrict the filter to only fuzz tests. +TEST_F(FuzzingModeCommandLineInterfaceTest, + RunsOnlyFuzzTestsWhenNoFilterIsSpecified) { + auto [status, std_out, std_err] = + RunWith({{"fuzz_for", "1ns"}}, /*env=*/{}, /*timeout=*/absl::Seconds(10), + "testdata/unit_test_and_fuzz_tests"); + + EXPECT_THAT(std_out, Not(HasSubstr("[ RUN ] UnitTest.AlwaysPasses"))); + EXPECT_THAT(std_out, HasSubstr("[ RUN ] FuzzTest.AlwaysPasses")); + EXPECT_THAT(std_out, HasSubstr("[ RUN ] FuzzTest.AlsoAlwaysPasses")); + EXPECT_THAT(std_out, HasSubstr("2 tests from 1 test suite ran.")); + EXPECT_THAT(status, Eq(ExitCode(0))); +} + +TEST_F(FuzzingModeCommandLineInterfaceTest, + AllowsSpecifyingFilterWithFuzzForDuration) { + auto [status, std_out, std_err] = + RunWith({{"fuzz_for", "1ns"}}, /*env=*/{}, /*timeout=*/absl::Seconds(10), + "testdata/unit_test_and_fuzz_tests", + {{GTEST_FLAG_PREFIX_ "filter", + "UnitTest.AlwaysPasses:FuzzTest.AlwaysPasses"}}); + + EXPECT_THAT(std_out, HasSubstr("[ RUN ] UnitTest.AlwaysPasses")); + EXPECT_THAT(std_out, HasSubstr("[ RUN ] FuzzTest.AlwaysPasses")); + EXPECT_THAT(std_out, + Not(HasSubstr("[ RUN ] FuzzTest.AlsoAlwaysPasses"))); + EXPECT_THAT(std_out, HasSubstr("2 tests from 2 test suites ran.")); + EXPECT_THAT(status, Eq(ExitCode(0))); +} + std::string CentipedePath() { const auto test_srcdir = absl::NullSafeStringView(getenv("TEST_SRCDIR")); FUZZTEST_INTERNAL_CHECK_PRECONDITION(
diff --git a/e2e_tests/testdata/BUILD b/e2e_tests/testdata/BUILD index 620a38e..ae40eef 100644 --- a/e2e_tests/testdata/BUILD +++ b/e2e_tests/testdata/BUILD
@@ -122,3 +122,13 @@ "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", ], ) + +cc_binary( + name = "unit_test_and_fuzz_tests", + testonly = 1, + srcs = ["unit_test_and_fuzz_tests.cc"], + deps = [ + "@com_google_fuzztest//fuzztest:fuzztest_core", + "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", + ], +)
diff --git a/e2e_tests/testdata/CMakeLists.txt b/e2e_tests/testdata/CMakeLists.txt index a46f818..36d28cf 100644 --- a/e2e_tests/testdata/CMakeLists.txt +++ b/e2e_tests/testdata/CMakeLists.txt
@@ -83,4 +83,15 @@ domain_tests.stripped PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/com_google_fuzztest/e2e_tests/testdata" +) + +add_executable( + unit_test_and_fuzz_tests.stripped + unit_test_and_fuzz_tests.cc +) +link_fuzztest(unit_test_and_fuzz_tests.stripped) +set_target_properties( + unit_test_and_fuzz_tests.stripped + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/com_google_fuzztest/e2e_tests/testdata" ) \ No newline at end of file
diff --git a/e2e_tests/testdata/unit_test_and_fuzz_tests.cc b/e2e_tests/testdata/unit_test_and_fuzz_tests.cc new file mode 100644 index 0000000..dc5d41c --- /dev/null +++ b/e2e_tests/testdata/unit_test_and_fuzz_tests.cc
@@ -0,0 +1,28 @@ +// Copyright 2024 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 "gtest/gtest.h" +#include "./fuzztest/fuzztest_core.h" + +namespace { + +TEST(UnitTest, AlwaysPasses) {} + +void AlwaysPasses(int) {} +FUZZ_TEST(FuzzTest, AlwaysPasses); + +void AlsoAlwaysPasses(int) {} +FUZZ_TEST(FuzzTest, AlsoAlwaysPasses); + +} // namespace
diff --git a/fuzztest/init_fuzztest.cc b/fuzztest/init_fuzztest.cc index e7a0531..0577e03 100644 --- a/fuzztest/init_fuzztest.cc +++ b/fuzztest/init_fuzztest.cc
@@ -75,10 +75,9 @@ absl::Duration, fuzz_for, absl::InfiniteDuration(), "Runs all fuzz tests in fuzzing mode for the specified duration. Can " "be combined with --" FUZZTEST_FLAG_PREFIX - "fuzz to select a single fuzz tests, or " - "with --" FUZZTEST_FLAG_PREFIX - "filter to select a subset of fuzz tests. Recommended " - "to use with test sharding."); + "fuzz to select a single fuzz tests, or with --" GTEST_FLAG_PREFIX_ + "filter to select a subset of fuzz tests. Recommended to use with test " + "sharding."); FUZZTEST_DEFINE_FLAG( std::string, corpus_database, @@ -277,6 +276,20 @@ const RunMode run_mode = is_test_to_fuzz_specified || has_time_limit_per_test ? RunMode::kFuzz : RunMode::kUnitTest; + + if (run_mode == RunMode::kFuzz && !is_test_to_fuzz_specified && + GTEST_FLAG_GET(filter) == "*") { + // Run only the fuzz tests, and not the unit tests when the user doesn't + // set the test filter. + // TODO: b/340232436 -- This is needed because we currently rely on a fuzz + // test being the first test to run so that Centipede can get the serialized + // configuration from the binary. For simplicity, we don't restrict the + // filter to fuzz tests when the user explicitly sets the filter. Instead of + // improving the logic here, once we fix b/340232436 we will remove this + // altogether and allow a mix of fuzz tests and unit tests in all cases. + GTEST_FLAG_SET(filter, absl::StrJoin(configuration.fuzz_tests, ":")); + } + // TODO(b/307513669): Use the Configuration class instead of Runtime. internal::Runtime::instance().SetRunMode(run_mode); }