// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and/or associated documentation files (the
// "Materials"), to deal in the Materials without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Materials, and to
// permit persons to whom the Materials are furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Materials.
//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
//    https://www.khronos.org/registry/
//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

#ifndef LIBSPIRV_TEST_TEST_FIXTURE_H_
#define LIBSPIRV_TEST_TEST_FIXTURE_H_

#include "UnitSPIRV.h"

namespace spvtest {

// 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.
  const SpirvVector::size_type kFirstInstruction = 5;

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

  virtual ~TextToBinaryTestBase() {
    DestroyBinary();
    if (diagnostic) spvDiagnosticDestroy(diagnostic);
    spvContextDestroy(context);
  }

  // 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& text) {
    spv_result_t status = spvTextToBinary(context, text.c_str(), text.size(),
                                          &binary, &diagnostic);
    EXPECT_EQ(SPV_SUCCESS, status) << text;
    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& text) {
    EXPECT_NE(SPV_SUCCESS, spvTextToBinary(context, text.c_str(), text.size(),
                                           &binary, &diagnostic))
        << text;
    DestroyBinary();
    return diagnostic->error;
  }

  // Encodes SPIR-V text into binary and then decodes the binary using
  // default options. Returns the decoded text.
  std::string EncodeAndDecodeSuccessfully(const std::string& text) {
    return EncodeAndDecodeSuccessfully(text, SPV_BINARY_TO_TEXT_OPTION_NONE);
  }

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

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

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

    // Remove the preamble comments generated by disassembler.
    const std::string schema0 = "Schema: 0\n";
    std::string::size_type preamble_end = decoded_string.find(schema0);
    return decoded_string.substr(preamble_end + schema0.size());
  }

  // 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& text, const SpirvVector& words_to_append) {
    SpirvVector code =
        spvtest::Concatenate({CompileSuccessfully(text), words_to_append});

    spv_text decoded_text;
    EXPECT_NE(SPV_SUCCESS, spvBinaryToText(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& text) {
    const SpirvVector code = CompileSuccessfully(text);
    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;
  }

  spv_context context;
  spv_diagnostic diagnostic;

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

using TextToBinaryTest = TextToBinaryTestBase<::testing::Test>;

}  // namespace spvtest

#endif  // LIBSPIRV_TEST_TEST_FIXTURE_H_
