diff --git a/test/common/init/BUILD b/test/common/init/BUILD index 894e7493aa72..e3b81a8e8a12 100644 --- a/test/common/init/BUILD +++ b/test/common/init/BUILD @@ -2,8 +2,10 @@ licenses(["notice"]) # Apache 2 load( "//bazel:envoy_build_system.bzl", + "envoy_cc_fuzz_test", "envoy_cc_test", "envoy_package", + "envoy_proto_library", ) envoy_package() @@ -32,3 +34,20 @@ envoy_cc_test( "//test/mocks/init:init_mocks", ], ) + +envoy_proto_library( + name = "init_fuzz_proto", + srcs = ["init_fuzz.proto"], + deps = ["//test/fuzz:common_proto"], +) + +envoy_cc_fuzz_test( + name = "init_fuzz_test", + srcs = ["init_fuzz_test.cc"], + corpus = "init_corpus", + deps = [ + ":init_fuzz_proto_cc_proto", + "//source/common/init:manager_lib", + "//test/fuzz:utility_lib", + ], +) diff --git a/test/common/init/init_corpus/m1t1 b/test/common/init/init_corpus/m1t1 new file mode 100644 index 000000000000..066a4b599b28 --- /dev/null +++ b/test/common/init/init_corpus/m1t1 @@ -0,0 +1,13 @@ +actions { + action: INIT_MANAGER_ADD_TARGET + param: 1 +} + +actions { + action: INIT_MANAGER_INITIALIZE + param: 1 +} +actions { + action: INIT_TARGET_READY + param: 1 +} \ No newline at end of file diff --git a/test/common/init/init_fuzz.proto b/test/common/init/init_fuzz.proto new file mode 100644 index 000000000000..ef8e1b48b61b --- /dev/null +++ b/test/common/init/init_fuzz.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + +package test.common.init; + +// Structured input for init_fuzz_test. + +enum InitEntityAction { + + // manager + INIT_MANAGER_CREATION = 0; + INIT_MANAGER_INITIALIZE = 1; + INIT_MANAGER_DESTRUCTION = 2; + + // target + INIT_TARGET_READY = 3; + INIT_TARGET_DESTRUCTION = 4; + + // watcher + INIT_WATCHER_DESTRUCTION = 5; + + // add + INIT_MANAGER_ADD_TARGET = 6; +} + +message InitAction { + InitEntityAction action = 1; + int32 param = 2; +} + +message InitTestCase { + repeated InitAction actions = 1; +} diff --git a/test/common/init/init_fuzz_test.cc b/test/common/init/init_fuzz_test.cc new file mode 100644 index 000000000000..71e247b52ee6 --- /dev/null +++ b/test/common/init/init_fuzz_test.cc @@ -0,0 +1,71 @@ +#include "common/common/assert.h" +#include "common/init/manager_impl.h" +#include "common/init/target_impl.h" +#include "common/init/watcher_impl.h" + +#include "test/common/init/init_fuzz.pb.h" +#include "test/fuzz/fuzz_runner.h" + +#include "absl/strings/str_cat.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Fuzz { +namespace { +using namespace Init; + +class InitDriver { +public: + InitDriver(int manager_size, int target_size) { + for (int i = 0; i < manager_size; i++) { + ms_.emplace_back(std::make_unique(absl::StrCat("fuzz_manager_", i))); + ws_.emplace_back(std::make_unique( + absl::StrCat("fuzz_watcher_", i), [this, i]() mutable { ready_flags_[i] = true; })); + ready_flags_.emplace_back(false); + } + for (int i = 0; i < target_size; i++) { + ts_.emplace_back(std::make_unique(absl::StrCat("fuzz_target_", i), []() {})); + } + } + + void transit(const test::common::init::InitAction& action) { + auto param = action.param(); + int mid = (param % 1); + int tid = (param % 1); + switch (action.action()) { + case test::common::init::INIT_MANAGER_INITIALIZE: + ms_[mid]->initialize(*ws_[mid]); + break; + case test::common::init::INIT_MANAGER_ADD_TARGET: + + ms_[mid]->add(*ts_[tid]); + break; + case test::common::init::INIT_TARGET_READY: + + ts_[tid]->ready(); + default: + // NOT_IMPLEMENT_YET + break; + } + }; + + std::vector ready_flags_; + std::vector> ms_; + std::vector> ts_; + std::vector> ws_; +}; + +DEFINE_PROTO_FUZZER(const test::common::init::InitTestCase& input) { + if (input.actions_size() < 3) { + return; + } + InitDriver driver(1, 1); + ENVOY_LOG_MISC(critical, "input size {}", input.actions_size()); + for (const auto& act : input.actions()) { + driver.transit(act); + } + RELEASE_ASSERT(driver.ready_flags_[0], "manager not initialized"); +} +} // namespace +} // namespace Fuzz +} // namespace Envoy \ No newline at end of file