| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| |
| #include <gtest/gtest.h> |
| |
| #include "src/sys/fuzzing/common/component-context.h" |
| #include "src/sys/fuzzing/common/input.h" |
| #include "src/sys/fuzzing/common/options.h" |
| #include "src/sys/fuzzing/common/testing/async-test.h" |
| #include "src/sys/fuzzing/framework/engine/adapter-client.h" |
| #include "src/sys/fuzzing/framework/engine/corpus.h" |
| |
| // These tests replaces the engine when building a fuzzer test instead of a fuzzer. |
| |
| namespace fuzzing { |
| |
| class FuzzerTest : public AsyncTest { |
| protected: |
| void SetUp() override { |
| AsyncTest::SetUp(); |
| options_ = MakeOptions(); |
| } |
| |
| const OptionsPtr& options() const { return options_; } |
| |
| std::unique_ptr<TargetAdapterClient> MakeClient() { |
| auto context = ComponentContext::CreateWithExecutor(executor()); |
| auto client = std::make_unique<TargetAdapterClient>(context->executor()); |
| client->set_handler(context->MakeRequestHandler<TargetAdapter>()); |
| TargetAdapterClient::AddDefaults(options_.get()); |
| client->Configure(options_); |
| return client; |
| } |
| |
| private: |
| OptionsPtr options_; |
| }; |
| |
| TEST_F(FuzzerTest, EmptyInputs) { |
| auto client = MakeClient(); |
| |
| // Should be able to handle empty inputs and repeated inputs. |
| Input input; |
| auto task = client->TestOneInput(input).and_then(client->TestOneInput(input)); |
| FUZZING_EXPECT_OK(std::move(task)); |
| RunUntilIdle(); |
| } |
| |
| TEST_F(FuzzerTest, SeedCorpus) { |
| auto client = MakeClient(); |
| |
| std::vector<std::string> parameters; |
| FUZZING_EXPECT_OK(client->GetParameters(), ¶meters); |
| RunUntilIdle(); |
| |
| auto seed_corpus_dirs = client->GetSeedCorpusDirectories(parameters); |
| Corpus seed_corpus; |
| auto options = this->options(); |
| Corpus::AddDefaults(options.get()); |
| seed_corpus.Configure(options); |
| seed_corpus.Load(seed_corpus_dirs); |
| |
| // Ensure only one call to |TestOneInput| is active at a time. |
| auto task = fpromise::make_promise( |
| [&, i = size_t(0), test_one = Future<>()](Context& context) mutable -> Result<> { |
| while (true) { |
| if (!test_one) { |
| Input input; |
| if (!seed_corpus.At(i, &input)) { |
| return fpromise::ok(); |
| } |
| test_one = client->TestOneInput(input); |
| } |
| if (!test_one(context)) { |
| return fpromise::pending(); |
| } |
| if (test_one.is_error()) { |
| return fpromise::error(); |
| } |
| test_one = nullptr; |
| ++i; |
| } |
| }); |
| FUZZING_EXPECT_OK(std::move(task)); |
| RunUntilIdle(); |
| } |
| |
| } // namespace fuzzing |