Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions e2e_tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ cc_test(
"@com_google_fuzztest//centipede:centipede_uninstrumented",
"@com_google_fuzztest//e2e_tests/testdata:data",
"@com_google_fuzztest//e2e_tests/testdata:dynamically_registered_fuzz_tests.stripped",
"@com_google_fuzztest//e2e_tests/testdata:fuzz_test_with_custom_main.stripped",
"@com_google_fuzztest//e2e_tests/testdata:fuzz_test_without_init_fuzztest.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:llvm_fuzzer_with_custom_mutator.stripped",
Expand Down
18 changes: 18 additions & 0 deletions e2e_tests/functional_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,24 @@ TEST_F(UnitTestModeTest, FuzzTestsRecordFuzzTestProperty) {
Optional(IsXmlWithExactlyFuzzTestsHavingFuzzTestProperty()));
}

TEST_F(UnitTestModeTest, FailsLoudlyWhenInitFuzzTestIsNotCalled) {
auto [status, std_out, std_err] =
RunWithExactFuzzerFlags("*", "testdata/fuzz_test_without_init_fuzztest");

EXPECT_THAT(status, Ne(ExitCode(0)));
EXPECT_THAT_LOG(
std_out, HasSubstr("FUZZ_TEST(MySuite, MyFuzzTest) was registered, but "
"InitFuzzTest was never called in main()."));
}

TEST_F(UnitTestModeTest, PassesWhenInitFuzzTestIsCalledInCustomMain) {
auto [status, std_out, std_err] =
RunWithExactFuzzerFlags("*", "testdata/fuzz_test_with_custom_main");

EXPECT_THAT(status, Eq(ExitCode(0)));
EXPECT_THAT_LOG(std_out, HasSubstr("[ PASSED ] 1 test."));
}

// Tests for the FuzzTest command line interface.
class GenericCommandLineInterfaceTest : public ::testing::Test {
protected:
Expand Down
21 changes: 21 additions & 0 deletions e2e_tests/testdata/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,27 @@ cc_binary(
],
)

cc_binary(
name = "fuzz_test_without_init_fuzztest",
testonly = 1,
srcs = ["fuzz_test_without_init_fuzztest.cc"],
deps = [
"@com_google_fuzztest//fuzztest",
"@googletest//:gtest",
],
)

cc_binary(
name = "fuzz_test_with_custom_main",
testonly = 1,
srcs = ["fuzz_test_with_custom_main.cc"],
deps = [
"@com_google_fuzztest//fuzztest",
"@com_google_fuzztest//fuzztest:init_fuzztest",
"@googletest//:gtest",
],
)

cc_binary(
name = "fuzz_tests_for_corpus_database_testing",
testonly = 1,
Expand Down
48 changes: 48 additions & 0 deletions e2e_tests/testdata/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,51 @@ set_target_properties(
PROPERTIES RUNTIME_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/_main/e2e_tests/testdata"
)

add_executable(
fuzz_test_without_init_fuzztest.stripped
fuzz_test_without_init_fuzztest.cc
)
if (APPLE)
target_link_libraries(
fuzz_test_without_init_fuzztest.stripped
PRIVATE
fuzztest::fuzztest
-Wl,-force_load,$<TARGET_FILE:fuzztest_init_fuzztest>
-Wl,-force_load,$<TARGET_FILE:fuzztest_googletest_adaptor>
GTest::gtest
)
else ()
target_link_libraries(
fuzz_test_without_init_fuzztest.stripped
PRIVATE
fuzztest::fuzztest
-Wl,--whole-archive
fuzztest::init_fuzztest
fuzztest::googletest_adaptor
-Wl,--no-whole-archive
GTest::gtest
)
endif ()
set_target_properties(
fuzz_test_without_init_fuzztest.stripped
PROPERTIES RUNTIME_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/_main/e2e_tests/testdata"
)

add_executable(
fuzz_test_with_custom_main.stripped
fuzz_test_with_custom_main.cc
)
target_link_libraries(
fuzz_test_with_custom_main.stripped
PRIVATE
fuzztest::fuzztest
fuzztest::init_fuzztest
GTest::gtest
)
set_target_properties(
fuzz_test_with_custom_main.stripped
PROPERTIES RUNTIME_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/_main/e2e_tests/testdata"
)
30 changes: 30 additions & 0 deletions e2e_tests/testdata/fuzz_test_with_custom_main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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
//
// https://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.h"
#include "fuzztest/init_fuzztest.h"

namespace {

void MyFuzzTest(int) {}
FUZZ_TEST(MySuite, MyFuzzTest);

} // namespace

int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
fuzztest::InitFuzzTest(&argc, &argv);
return RUN_ALL_TESTS();
}
28 changes: 28 additions & 0 deletions e2e_tests/testdata/fuzz_test_without_init_fuzztest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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
//
// https://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.h"

namespace {

void MyFuzzTest(int) {}
FUZZ_TEST(MySuite, MyFuzzTest);

} // namespace

int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
2 changes: 2 additions & 0 deletions fuzztest/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ config_setting(

cc_library(
name = "fuzztest",
testonly = True,
hdrs = ["fuzztest.h"],
deps = [
":domain",
":fuzztest_macros",
":init_fuzztest",
],
)

Expand Down
1 change: 1 addition & 0 deletions fuzztest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ fuzztest_cc_library(
DEPS
fuzztest::domain
fuzztest::fuzztest_macros
fuzztest::init_fuzztest
)

fuzztest_cc_library(
Expand Down
1 change: 1 addition & 0 deletions fuzztest/fuzztest.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// IWYU pragma: begin_exports
#include "./fuzztest/domain.h"
#include "./fuzztest/fuzztest_macros.h"
#include "./fuzztest/init_fuzztest.h"
// IWYU pragma: end_exports

#endif // FUZZTEST_FUZZTEST_FUZZTEST_H_
5 changes: 4 additions & 1 deletion fuzztest/init_fuzztest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ void RunSpecifiedFuzzTest(std::string_view name, std::string_view binary_id) {

void InitFuzzTest(int* argc, char*** argv, std::string_view binary_id) {
auto& runtime = internal::Runtime::instance();
runtime.SetInitFuzzTestCalled(true);
runtime.SetArgs(argc, argv);
const bool is_listing = absl::GetFlag(FUZZTEST_FLAG(list_fuzz_tests));
if (is_listing) {
for (const auto& name : ListRegisteredTests()) {
Expand Down Expand Up @@ -482,7 +484,8 @@ void InitFuzzTest(int* argc, char*** argv, std::string_view binary_id) {
internal::Configuration configuration =
CreateConfigurationsFromFlags(derived_binary_id);
configuration.reproduction_command_template = reproduction_command_template;
internal::RegisterFuzzTestsAsGoogleTests(argc, argv, configuration);
runtime.SetConfiguration(configuration);
internal::RegisterSeparateRegressionTestsForEachCrashingInput(configuration);

const bool is_fuzzing_or_replaying =
(fuzzing_time_limit || replay_corpus_time_limit);
Expand Down
50 changes: 26 additions & 24 deletions fuzztest/internal/googletest_adaptor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "./fuzztest/internal/googletest_adaptor.h"

#include <cstdlib>
#include <optional>
#include <string>
#include <type_traits>
#include <utility>
Expand All @@ -25,12 +26,13 @@

namespace fuzztest::internal {

std::vector<std::string> GTest_TestAdaptor::GetFuzzTestsInCurrentShard() const {
std::vector<std::string> GTest_TestAdaptor::GetFuzzTestsInCurrentShard(
const Configuration& configuration) const {
std::vector<std::string> result;
for (const auto* test : GetRegisteredTests()) {
if (!test->should_run()) continue;
if (test->is_in_another_shard()) continue;
for (const auto& fuzztest : configuration_.fuzz_tests) {
for (const auto& fuzztest : configuration.fuzz_tests) {
if (fuzztest ==
absl::StrCat(test->test_suite_name(), ".", test->name())) {
result.push_back(fuzztest);
Expand All @@ -43,13 +45,13 @@ std::vector<std::string> GTest_TestAdaptor::GetFuzzTestsInCurrentShard() const {

namespace {
template <typename T>
void RegisterFuzzTestAsGTest(int* argc, char*** argv, FuzzTest& test,
const Configuration& configuration,
absl::string_view crashing_input_path = "") {
auto fixture_factory = [argc, argv, &test,
configuration = configuration]() mutable -> T* {
void RegisterFuzzTestAsGTest(
FuzzTest& test, std::optional<Configuration> configuration = std::nullopt,
absl::string_view crashing_input_path = "") {
auto fixture_factory = [&test, configuration =
std::move(configuration)]() mutable -> T* {
return new ::fuzztest::internal::GTest_TestAdaptor(
test, argc, argv, std::move(configuration));
test, std::move(configuration));
};
if (crashing_input_path.empty()) {
::testing::RegisterTest(test.suite_name().c_str(), test.test_name().c_str(),
Expand All @@ -73,8 +75,7 @@ void RegisterFuzzTestAsGTest(int* argc, char*** argv, FuzzTest& test,

template <typename T>
void RegisterSeparateRegressionTestForEachCrashingInput(
int* argc, char*** argv, FuzzTest& test,
const Configuration& configuration) {
FuzzTest& test, const Configuration& configuration) {
if (!configuration.reproduce_findings_as_separate_tests) return;
#ifdef FUZZTEST_USE_CENTIPEDE
const std::vector<std::string> crash_inputs =
Expand All @@ -87,28 +88,29 @@ void RegisterSeparateRegressionTestForEachCrashingInput(
for (const std::string& input : crash_inputs) {
Configuration updated_configuration = configuration;
updated_configuration.crashing_input_to_reproduce = input;
RegisterFuzzTestAsGTest<T>(argc, argv, test, updated_configuration, input);
RegisterFuzzTestAsGTest<T>(test, updated_configuration, input);
}
}

template <typename T>
void RegisterTests(int* argc, char*** argv, FuzzTest& test,
const Configuration& configuration) {
RegisterFuzzTestAsGTest<T>(argc, argv, test, configuration);
RegisterSeparateRegressionTestForEachCrashingInput<T>(argc, argv, test,
configuration);
}

} // namespace

void RegisterFuzzTestsAsGoogleTests(int* argc, char*** argv,
const Configuration& configuration) {
void RegisterFuzzTestAsGoogleTest(FuzzTest& test) {
if (test.uses_fixture()) {
RegisterFuzzTestAsGTest<::fuzztest::internal::GTest_TestAdaptor>(test);
} else {
RegisterFuzzTestAsGTest<::testing::Test>(test);
}
}

void RegisterSeparateRegressionTestsForEachCrashingInput(
const Configuration& configuration) {
::fuzztest::internal::ForEachTest([&](auto& test) {
if (test.uses_fixture()) {
RegisterTests<::fuzztest::internal::GTest_TestAdaptor>(argc, argv, test,
configuration);
RegisterSeparateRegressionTestForEachCrashingInput<
::fuzztest::internal::GTest_TestAdaptor>(test, configuration);
} else {
RegisterTests<::testing::Test>(argc, argv, test, configuration);
RegisterSeparateRegressionTestForEachCrashingInput<::testing::Test>(
test, configuration);
}
});

Expand Down
Loading
Loading