// 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 "fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.h"

#include <fstream>
#include <utility>

#include "fuzzers/tint_spirv_tools_fuzzer/util.h"
#include "source/opt/build_module.h"

namespace tint {
namespace fuzzers {
namespace spvtools_fuzzer {

SpirvFuzzMutator::SpirvFuzzMutator(
    spv_target_env target_env,
    std::vector<uint32_t> binary,
    unsigned seed,
    const std::vector<spvtools::fuzz::fuzzerutil::ModuleSupplier>& donors,
    bool enable_all_passes,
    spvtools::fuzz::RepeatedPassStrategy repeated_pass_strategy,
    bool validate_after_each_pass,
    uint32_t transformation_batch_size)
    : transformation_batch_size_(transformation_batch_size),
      errors_(std::make_unique<std::stringstream>()),
      fuzzer_(nullptr),
      validator_options_(),
      original_binary_(std::move(binary)),
      seed_(seed) {
  auto ir_context = spvtools::BuildModule(
      target_env, spvtools::fuzz::fuzzerutil::kSilentMessageConsumer,
      original_binary_.data(), original_binary_.size());
  assert(ir_context && "|binary| is invalid");

  auto transformation_context =
      std::make_unique<spvtools::fuzz::TransformationContext>(
          std::make_unique<spvtools::fuzz::FactManager>(ir_context.get()),
          validator_options_);

  auto fuzzer_context = std::make_unique<spvtools::fuzz::FuzzerContext>(
      std::make_unique<spvtools::fuzz::PseudoRandomGenerator>(seed),
      spvtools::fuzz::FuzzerContext::GetMinFreshId(ir_context.get()), false);
  fuzzer_ = std::make_unique<spvtools::fuzz::Fuzzer>(
      std::move(ir_context), std::move(transformation_context),
      std::move(fuzzer_context), util::GetBufferMessageConsumer(errors_.get()),
      donors, enable_all_passes, repeated_pass_strategy,
      validate_after_each_pass, validator_options_);
}

Mutator::Result SpirvFuzzMutator::Mutate() {
  // The assertion will fail in |fuzzer_->Run| if the previous fuzzing led to
  // invalid module.
  auto result = fuzzer_->Run(transformation_batch_size_);
  switch (result.status) {
    case spvtools::fuzz::Fuzzer::Status::kComplete:
      return {Mutator::Status::kComplete, result.is_changed};
    case spvtools::fuzz::Fuzzer::Status::kModuleTooBig:
    case spvtools::fuzz::Fuzzer::Status::kTransformationLimitReached:
      return {Mutator::Status::kLimitReached, result.is_changed};
    case spvtools::fuzz::Fuzzer::Status::kFuzzerStuck:
      return {Mutator::Status::kStuck, result.is_changed};
    case spvtools::fuzz::Fuzzer::Status::kFuzzerPassLedToInvalidModule:
      return {Mutator::Status::kInvalid, result.is_changed};
  }
}

std::vector<uint32_t> SpirvFuzzMutator::GetBinary() const {
  std::vector<uint32_t> result;
  fuzzer_->GetIRContext()->module()->ToBinary(&result, true);
  return result;
}

std::string SpirvFuzzMutator::GetErrors() const {
  return errors_->str();
}

void SpirvFuzzMutator::LogErrors(const std::string* path,
                                 uint32_t count) const {
  auto message = GetErrors();
  std::cout << count << " | SpirvFuzzMutator (seed: " << seed_ << ")"
            << std::endl;
  std::cout << message << std::endl;

  if (path) {
    auto prefix = *path + std::to_string(count);

    // Write errors to file.
    std::ofstream(prefix + ".fuzzer.log") << "seed: " << seed_ << std::endl
                                          << message << std::endl;

    // Write the invalid SPIR-V binary.
    util::WriteBinary(prefix + ".fuzzer.invalid.spv", GetBinary());

    // Write the original SPIR-V binary.
    util::WriteBinary(prefix + ".fuzzer.original.spv", original_binary_);

    // Write transformations.
    google::protobuf::util::JsonOptions options;
    options.add_whitespace = true;
    std::string json;
    google::protobuf::util::MessageToJsonString(
        fuzzer_->GetTransformationSequence(), &json, options);
    std::ofstream(prefix + ".fuzzer.transformations.json") << json << std::endl;

    std::ofstream binary_transformations(
        prefix + ".fuzzer.transformations.binary",
        std::ios::binary | std::ios::out);
    fuzzer_->GetTransformationSequence().SerializeToOstream(
        &binary_transformations);
  }
}

}  // namespace spvtools_fuzzer
}  // namespace fuzzers
}  // namespace tint
