// Copyright 2021 The Tint Authors.
//
// 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 <cstddef>
#include <cstdint>

#include "src/tint/fuzzers/random_generator.h"
#include "src/tint/fuzzers/tint_ast_fuzzer/cli.h"
#include "src/tint/fuzzers/tint_ast_fuzzer/mutator.h"
#include "src/tint/fuzzers/tint_ast_fuzzer/override_cli_params.h"
#include "src/tint/fuzzers/tint_common_fuzzer.h"
#include "src/tint/fuzzers/transform_builder.h"
#include "src/tint/lang/wgsl/ast_writer/generator.h"
#include "src/tint/lang/wgsl/reader/parser.h"
#include "testing/libfuzzer/libfuzzer_exports.h"

namespace tint::fuzzers::ast_fuzzer {
namespace {

CliParams cli_params{};

extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
    // Parse CLI parameters. `ParseCliParams` will call `exit` if some parameter
    // is invalid.
    cli_params = ParseCliParams(argc, *argv);
    // For some fuzz targets it is desirable to force the values of certain CLI
    // parameters after parsing.
    OverrideCliParams(cli_params);
    return 0;
}

extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data,
                                          size_t size,
                                          size_t max_size,
                                          unsigned seed) {
    Source::File file("test.wgsl", {reinterpret_cast<char*>(data), size});
    auto program = reader::wgsl::Parse(&file);
    if (!program.IsValid()) {
        std::cout << "Trying to mutate an invalid program:" << std::endl
                  << program.Diagnostics().str() << std::endl;
        return 0;
    }

    // Run the mutator.
    RandomGenerator generator(seed);
    ProbabilityContext probability_context(&generator);
    program = Mutate(std::move(program), &probability_context, cli_params.enable_all_mutations,
                     cli_params.mutation_batch_size, nullptr);

    if (!program.IsValid()) {
        std::cout << "Mutator produced invalid WGSL:" << std::endl
                  << "  seed: " << seed << std::endl
                  << program.Diagnostics().str() << std::endl;
        return 0;
    }

    auto result = writer::wgsl::Generate(&program, writer::wgsl::Options());
    if (!result.success) {
        std::cout << "Can't generate WGSL for a valid tint::Program:" << std::endl
                  << result.error << std::endl;
        return 0;
    }

    if (result.wgsl.size() > max_size) {
        return 0;
    }

    // No need to worry about the \0 here. The reason is that if \0 is included by
    // developer by mistake, it will be considered a part of the string and will
    // cause all sorts of strange bugs. Thus, unless `data` below is used as a raw
    // C string, the \0 symbol should be ignored.
    std::memcpy(  // NOLINT - clang-tidy warns about lack of null termination.
        data, result.wgsl.data(), result.wgsl.size());
    return result.wgsl.size();
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    if (size == 0) {
        return 0;
    }

    struct Target {
        FuzzingTarget fuzzing_target;
        OutputFormat output_format;
        const char* name;
    };

    Target targets[] = {{FuzzingTarget::kWgsl, OutputFormat::kWGSL, "WGSL"},
                        {FuzzingTarget::kHlsl, OutputFormat::kHLSL, "HLSL"},
                        {FuzzingTarget::kMsl, OutputFormat::kMSL, "MSL"},
                        {FuzzingTarget::kSpv, OutputFormat::kSpv, "SPV"}};

    for (auto target : targets) {
        if ((target.fuzzing_target & cli_params.fuzzing_target) != target.fuzzing_target) {
            continue;
        }

        TransformBuilder tb(data, size);
        tb.AddTransform<tint::ast::transform::Robustness>();

        CommonFuzzer fuzzer(InputFormat::kWGSL, target.output_format);
        fuzzer.SetTransformManager(tb.manager(), tb.data_map());

        fuzzer.Run(data, size);
        if (fuzzer.HasErrors()) {
            std::cout << "Fuzzing " << target.name << " produced an error" << std::endl;
            auto printer = tint::diag::Printer::create(stderr, true);
            tint::diag::Formatter{}.format(fuzzer.Diagnostics(), printer.get());
        }
    }

    return 0;
}

}  // namespace
}  // namespace tint::fuzzers::ast_fuzzer
