// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// 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 TEST_TEST_FIXTURE_H_
#define TEST_TEST_FIXTURE_H_

#include <algorithm>
#include <string>
#include <vector>

#include "test/unit_spirv.h"

namespace spvtest {

// RAII for spv_context.
struct ScopedContext {
  ScopedContext(spv_target_env env = SPV_ENV_UNIVERSAL_1_0)
      : context(spvContextCreate(env)) {}
  ~ScopedContext() { spvContextDestroy(context); }
  spv_context context;
};

// Common setup for TextToBinary tests. SetText() should be called to populate
// the actual test text.
template <typename T>
class TextToBinaryTestBase : public T {
 public:
  // Shorthand for SPIR-V compilation result.
  using SpirvVector = std::vector<uint32_t>;

  // Offset into a SpirvVector at which the first instruction starts.
  static const SpirvVector::size_type kFirstInstruction = 5;

  TextToBinaryTestBase() : diagnostic(nullptr), text(), binary(nullptr) {
    char textStr[] = "substitute the text member variable with your test";
    text = {textStr, strlen(textStr)};
  }

  ~TextToBinaryTestBase() override {
    DestroyBinary();
    if (diagnostic) spvDiagnosticDestroy(diagnostic);
  }

  // Returns subvector v[from:end).
  SpirvVector Subvector(const SpirvVector& v, SpirvVector::size_type from) {
    assert(from <= v.size());
    return SpirvVector(v.begin() + from, v.end());
  }

  // Compiles SPIR-V text in the given assembly syntax format, asserting
  // compilation success. Returns the compiled code.
  SpirvVector CompileSuccessfully(const std::string& txt,
                                  spv_target_env env = SPV_ENV_UNIVERSAL_1_0) {
    DestroyBinary();
    DestroyDiagnostic();
    spv_result_t status =
        spvTextToBinary(ScopedContext(env).context, txt.c_str(), txt.size(),
                        &binary, &diagnostic);
    EXPECT_EQ(SPV_SUCCESS, status) << txt;
    SpirvVector code_copy;
    if (status == SPV_SUCCESS) {
      code_copy = SpirvVector(binary->code, binary->code + binary->wordCount);
      DestroyBinary();
    } else {
      spvDiagnosticPrint(diagnostic);
    }
    return code_copy;
  }

  // Compiles SPIR-V text with the given format, asserting compilation failure.
  // Returns the error message(s).
  std::string CompileFailure(const std::string& txt,
                             spv_target_env env = SPV_ENV_UNIVERSAL_1_0) {
    DestroyBinary();
    DestroyDiagnostic();
    EXPECT_NE(SPV_SUCCESS,
              spvTextToBinary(ScopedContext(env).context, txt.c_str(),
                              txt.size(), &binary, &diagnostic))
        << txt;
    DestroyBinary();
    return diagnostic->error;
  }

  // Potentially flip the words in the binary representation to the other
  // endianness
  template <class It>
  void MaybeFlipWords(bool flip_words, It begin, It end) {
    SCOPED_TRACE(flip_words ? "Flipped Endianness" : "Normal Endianness");
    if (flip_words) {
      std::transform(begin, end, begin, [](const uint32_t raw_word) {
        return spvFixWord(raw_word, I32_ENDIAN_HOST == I32_ENDIAN_BIG
                                        ? SPV_ENDIANNESS_LITTLE
                                        : SPV_ENDIANNESS_BIG);
      });
    }
  }

  // Encodes SPIR-V text into binary and then decodes the binary using
  // given options. Returns the decoded text.
  std::string EncodeAndDecodeSuccessfully(
      const std::string& txt,
      uint32_t disassemble_options = SPV_BINARY_TO_TEXT_OPTION_NONE,
      spv_target_env env = SPV_ENV_UNIVERSAL_1_0, bool flip_words = false) {
    DestroyBinary();
    DestroyDiagnostic();
    ScopedContext context(env);
    disassemble_options |= SPV_BINARY_TO_TEXT_OPTION_NO_HEADER;
    spv_result_t error = spvTextToBinary(context.context, txt.c_str(),
                                         txt.size(), &binary, &diagnostic);
    if (error) {
      spvDiagnosticPrint(diagnostic);
      spvDiagnosticDestroy(diagnostic);
    }
    EXPECT_EQ(SPV_SUCCESS, error);
    if (!binary) return "";

    MaybeFlipWords(flip_words, binary->code, binary->code + binary->wordCount);

    spv_text decoded_text;
    error = spvBinaryToText(context.context, binary->code, binary->wordCount,
                            disassemble_options, &decoded_text, &diagnostic);
    if (error) {
      spvDiagnosticPrint(diagnostic);
      spvDiagnosticDestroy(diagnostic);
    }
    EXPECT_EQ(SPV_SUCCESS, error) << txt;

    const std::string decoded_string = decoded_text->str;
    spvTextDestroy(decoded_text);

    return decoded_string;
  }

  // Encodes SPIR-V text into binary. This is expected to succeed.
  // The given words are then appended to the binary, and the result
  // is then decoded. This is expected to fail.
  // Returns the error message.
  std::string EncodeSuccessfullyDecodeFailed(
      const std::string& txt, const SpirvVector& words_to_append) {
    DestroyBinary();
    DestroyDiagnostic();
    SpirvVector code =
        spvtest::Concatenate({CompileSuccessfully(txt), words_to_append});

    spv_text decoded_text;
    EXPECT_NE(SPV_SUCCESS,
              spvBinaryToText(ScopedContext().context, code.data(), code.size(),
                              SPV_BINARY_TO_TEXT_OPTION_NONE, &decoded_text,
                              &diagnostic));
    if (diagnostic) {
      std::string error_message = diagnostic->error;
      spvDiagnosticDestroy(diagnostic);
      diagnostic = nullptr;
      return error_message;
    }
    return "";
  }

  // Compiles SPIR-V text, asserts success, and returns the words representing
  // the instructions.  In particular, skip the words in the SPIR-V header.
  SpirvVector CompiledInstructions(const std::string& txt,
                                   spv_target_env env = SPV_ENV_UNIVERSAL_1_0) {
    const SpirvVector code = CompileSuccessfully(txt, env);
    SpirvVector result;
    // Extract just the instructions.
    // If the code fails to compile, then return the empty vector.
    // In any case, don't crash or invoke undefined behaviour.
    if (code.size() >= kFirstInstruction)
      result = Subvector(code, kFirstInstruction);
    return result;
  }

  void SetText(const std::string& code) {
    textString = code;
    text.str = textString.c_str();
    text.length = textString.size();
  }

  // Destroys the binary, if it exists.
  void DestroyBinary() {
    spvBinaryDestroy(binary);
    binary = nullptr;
  }

  // Destroys the diagnostic, if it exists.
  void DestroyDiagnostic() {
    spvDiagnosticDestroy(diagnostic);
    diagnostic = nullptr;
  }

  spv_diagnostic diagnostic;

  std::string textString;
  spv_text_t text;
  spv_binary binary;
};

using TextToBinaryTest = TextToBinaryTestBase<::testing::Test>;
}  // namespace spvtest

using RoundTripTest =
    spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;

#endif  // TEST_TEST_FIXTURE_H_
