blob: ad93fbcc1f8e17f21b3133ed0e222d14049967d9 [file] [log] [blame]
// 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_GOOGLETEST_ADAPTOR_H_
#define FUZZTEST_FUZZTEST_GOOGLETEST_ADAPTOR_H_
#include <utility>
#include "gtest/gtest.h"
#include "./fuzztest/internal/registry.h"
#include "./fuzztest/internal/runtime.h"
#define GOOGLEFUZZTEST_REGISTER_FOR_GOOGLETEST(selected_run_mode, argc, argv) \
(::fuzztest::internal::ForEachTest([&](const auto& test) { \
auto fixture_factory = \
[argc, argv, &test]() -> ::fuzztest::internal::GTest_TestAdaptor* { \
return new ::fuzztest::internal::GTest_TestAdaptor(test, argc, argv); \
}; \
auto test_factory = [argc, argv, &test]() -> ::testing::Test* { \
return new ::fuzztest::internal::GTest_TestAdaptor(test, argc, argv); \
}; \
if (test.uses_fixture()) { \
::testing::RegisterTest(test.suite_name(), test.test_name(), nullptr, \
nullptr, test.file(), test.line(), \
std::move(fixture_factory)); \
} else { \
::testing::RegisterTest(test.suite_name(), test.test_name(), nullptr, \
nullptr, test.file(), test.line(), \
std::move(test_factory)); \
} \
}), \
::testing::UnitTest::GetInstance()->listeners().Append( \
new ::fuzztest::internal::GTest_EventListener< \
::testing::EmptyTestEventListener, ::testing::TestPartResult>()), \
::fuzztest::internal::run_mode = selected_run_mode)
namespace fuzztest::internal {
class GTest_TestAdaptor : public ::testing::Test {
public:
explicit GTest_TestAdaptor(const FuzzTest& test, int* argc, char*** argv)
: test_(test), argc_(argc), argv_(argv) {}
void TestBody() override {
auto test = test_.make();
if (run_mode == RunMode::kUnitTest) {
test->RunInUnitTestMode();
} else {
ASSERT_EQ(0, test->RunInFuzzingMode(argc_, argv_)) << "Fuzzing failure.";
}
}
static void SetUpTestSuite() {
SetUpTearDownTestSuiteFunction set_up_test_suite = GetSetUpTestSuite(
testing::UnitTest::GetInstance()->current_test_suite()->name());
if (set_up_test_suite != nullptr) set_up_test_suite();
}
static void TearDownTestSuite() {
SetUpTearDownTestSuiteFunction tear_down_test_suite = GetTearDownTestSuite(
testing::UnitTest::GetInstance()->current_test_suite()->name());
if (tear_down_test_suite != nullptr) tear_down_test_suite();
}
private:
const FuzzTest& test_;
int* argc_;
char*** argv_;
};
template <typename Base, typename TestPartResult>
class GTest_EventListener : public Base {
public:
void OnTestPartResult(const TestPartResult& test_part_result) override {
if (!test_part_result.failed()) return;
if (run_mode == RunMode::kFuzz) {
// The SIGABRT will trigger a report.
std::abort();
} else {
// Otherwise, we report it manually.
on_failure.PrintReportOnDefaultSink();
}
external_failure_was_detected.store(true, std::memory_order_relaxed);
}
};
} // namespace fuzztest::internal
#endif // FUZZTEST_FUZZTEST_GOOGLETEST_ADAPTOR_H_