// Copyright 2020 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef SRC_TINT_LANG_SPIRV_READER_AST_PARSER_HELPER_TEST_H_
#define SRC_TINT_LANG_SPIRV_READER_AST_PARSER_HELPER_TEST_H_

#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

#include "src/tint/utils/macros/compiler.h"

TINT_BEGIN_DISABLE_WARNING(NEWLINE_EOF);
TINT_BEGIN_DISABLE_WARNING(OLD_STYLE_CAST);
TINT_BEGIN_DISABLE_WARNING(SIGN_CONVERSION);
TINT_BEGIN_DISABLE_WARNING(WEAK_VTABLES);
#include "source/opt/ir_context.h"
TINT_END_DISABLE_WARNING(WEAK_VTABLES);
TINT_END_DISABLE_WARNING(SIGN_CONVERSION);
TINT_END_DISABLE_WARNING(OLD_STYLE_CAST);
TINT_END_DISABLE_WARNING(NEWLINE_EOF);

#include "gtest/gtest.h"
#include "src/tint/lang/spirv/reader/ast_parser/ast_parser.h"
#include "src/tint/lang/spirv/reader/ast_parser/fail_stream.h"
#include "src/tint/lang/spirv/reader/ast_parser/function.h"
#include "src/tint/lang/spirv/reader/ast_parser/namer.h"
#include "src/tint/lang/spirv/reader/ast_parser/spirv_tools_helpers_test.h"
#include "src/tint/lang/spirv/reader/ast_parser/usage.h"

namespace tint::spirv::reader::ast_parser::test {

/// A test class that wraps ParseImpl
class ASTParserWrapperForTest {
  public:
    /// Constructor
    /// @param input the input data to parse
    explicit ASTParserWrapperForTest(const std::vector<uint32_t>& input);
    /// Dumps SPIR-V if the conversion succeeded, then destroys the wrapper.
    ~ASTParserWrapperForTest();

    /// Sets global state to force dumping of the assembly text of succesfully
    /// SPIR-V.
    static void DumpSuccessfullyConvertedSpirv() { dump_successfully_converted_spirv_ = true; }
    /// Marks the test has having deliberately invalid SPIR-V
    void DeliberatelyInvalidSpirv() { skip_dumping_spirv_ = true; }
    /// Marks the test's SPIR-V as not being suitable for dumping, for a stated
    /// reason.
    void SkipDumpingPending(std::string) { skip_dumping_spirv_ = true; }

    /// @returns a new function emitter for the given function ID.
    /// Assumes ASTParser::BuildInternalRepresentation has been run and
    /// succeeded.
    /// @param function_id the SPIR-V identifier of the function
    FunctionEmitter function_emitter(uint32_t function_id) {
        auto* spirv_function = impl_.ir_context()->GetFunction(function_id);
        return FunctionEmitter(&impl_, *spirv_function);
    }

    /// Run the parser
    /// @returns true if the parse was successful, false otherwise.
    bool Parse() { return impl_.Parse(); }

    /// @returns the program. The program builder in the parser will be reset
    /// after this.
    Program program() { return impl_.Program(resolve_); }

    /// @returns the namer object
    Namer& namer() { return impl_.namer(); }

    /// @returns a reference to the internal builder, without building the
    /// program. To be used only for testing.
    ProgramBuilder& builder() { return impl_.builder(); }

    /// @returns the accumulated error string
    const std::string error() { return impl_.error(); }

    /// @return true if failure has not yet occurred
    bool success() { return impl_.success(); }

    /// Logs failure, ands return a failure stream to accumulate diagnostic
    /// messages. By convention, a failure should only be logged along with
    /// a non-empty string diagnostic.
    /// @returns the failure stream
    FailStream& Fail() { return impl_.Fail(); }

    /// @returns a borrowed pointer to the internal representation of the module.
    /// This is null until BuildInternalModule has been called.
    spvtools::opt::IRContext* ir_context() { return impl_.ir_context(); }

    /// Builds the internal representation of the SPIR-V module.
    /// Assumes the module is somewhat well-formed.  Normally you
    /// would want to validate the SPIR-V module before attempting
    /// to build this internal representation. Also computes a topological
    /// ordering of the functions.
    /// This is a no-op if the parser has already failed.
    /// @returns true if the parser is still successful.
    bool BuildInternalModule() { return impl_.BuildInternalModule(); }

    /// Builds an internal representation of the SPIR-V binary,
    /// and parses the module, except functions, into a Tint AST module.
    /// Diagnostics are emitted to the error stream.
    /// @returns true if it was successful.
    bool BuildAndParseInternalModuleExceptFunctions() {
        return impl_.BuildAndParseInternalModuleExceptFunctions();
    }

    /// Builds an internal representation of the SPIR-V binary,
    /// and parses it into a Tint AST module.  Diagnostics are emitted
    /// to the error stream.
    /// @returns true if it was successful.
    bool BuildAndParseInternalModule() { return impl_.BuildAndParseInternalModule(); }

    /// Registers user names for SPIR-V objects, from OpName, and OpMemberName.
    /// Also synthesizes struct field names.  Ensures uniqueness for names for
    /// SPIR-V IDs, and uniqueness of names of fields within any single struct.
    /// This is a no-op if the parser has already failed.
    /// @returns true if parser is still successful.
    bool RegisterUserAndStructMemberNames() { return impl_.RegisterUserAndStructMemberNames(); }

    /// Register Tint AST types for SPIR-V types, including type aliases as
    /// needed.  This is a no-op if the parser has already failed.
    /// @returns true if parser is still successful.
    bool RegisterTypes() { return impl_.RegisterTypes(); }

    /// Register sampler and texture usage for memory object declarations.
    /// This must be called after we've registered line numbers for all
    /// instructions. This is a no-op if the parser has already failed.
    /// @returns true if parser is still successful.
    bool RegisterHandleUsage() { return impl_.RegisterHandleUsage(); }

    /// Emits module-scope variables.
    /// This is a no-op if the parser has already failed.
    /// @returns true if parser is still successful.
    bool EmitModuleScopeVariables() { return impl_.EmitModuleScopeVariables(); }

    /// @returns the set of SPIR-V IDs for imports of the "GLSL.std.450"
    /// extended instruction set.
    const std::unordered_set<uint32_t>& glsl_std_450_imports() const {
        return impl_.glsl_std_450_imports();
    }

    /// Converts a SPIR-V type to a Tint type, and saves it for fast lookup.
    /// If the type is only used for builtins, then register that specially,
    /// and return null.  If the type is a sampler, image, or sampled image, then
    /// return the Void type, because those opaque types are handled in a
    /// different way.
    /// On failure, logs an error and returns null.  This should only be called
    /// after the internal representation of the module has been built.
    /// @param id the SPIR-V ID of a type.
    /// @returns a Tint type, or nullptr
    const Type* ConvertType(uint32_t id) { return impl_.ConvertType(id); }

    /// Gets the list of decorations for a SPIR-V result ID.  Returns an empty
    /// vector if the ID is not a result ID, or if no decorations target that ID.
    /// The internal representation must have already been built.
    /// @param id SPIR-V ID
    /// @returns the list of decorations on the given ID
    DecorationList GetDecorationsFor(uint32_t id) const { return impl_.GetDecorationsFor(id); }

    /// Gets the list of decorations for the member of a struct.  Returns an empty
    /// list if the `id` is not the ID of a struct, or if the member index is out
    /// of range, or if the target member has no decorations.
    /// The internal representation must have already been built.
    /// @param id SPIR-V ID of a struct
    /// @param member_index the member within the struct
    /// @returns the list of decorations on the member
    DecorationList GetDecorationsForMember(uint32_t id, uint32_t member_index) const {
        return impl_.GetDecorationsForMember(id, member_index);
    }

    /// Converts a SPIR-V struct member decoration into a number of AST
    /// decorations. If the decoration is recognized but deliberately dropped,
    /// then returns an empty list without a diagnostic. On failure, emits a
    /// diagnostic and returns an empty list.
    /// @param struct_type_id the ID of the struct type
    /// @param member_index the index of the member
    /// @param member_ty the type of the member
    /// @param decoration an encoded SPIR-V Decoration
    /// @returns the AST decorations
    auto ConvertMemberDecoration(uint32_t struct_type_id,
                                 uint32_t member_index,
                                 const Type* member_ty,
                                 const Decoration& decoration) {
        return impl_.ConvertMemberDecoration(struct_type_id, member_index, member_ty, decoration);
    }

    /// For a SPIR-V ID that might define a sampler, image, or sampled image
    /// value, return the SPIR-V instruction that represents the memory object
    /// declaration for the object.  If we encounter an OpSampledImage along the
    /// way, follow the image operand when follow_image is true; otherwise follow
    /// the sampler operand. Returns nullptr if we can't trace back to a memory
    /// object declaration.  Emits an error and returns nullptr when the scan
    /// fails due to a malformed module. This method can be used any time after
    /// BuildInternalModule has been invoked.
    /// @param id the SPIR-V ID of the sampler, image, or sampled image
    /// @param follow_image indicates whether to follow the image operand of
    /// OpSampledImage
    /// @returns the memory object declaration for the handle, or nullptr
    const spvtools::opt::Instruction* GetMemoryObjectDeclarationForHandle(uint32_t id,
                                                                          bool follow_image) {
        return impl_.GetMemoryObjectDeclarationForHandle(id, follow_image);
    }

    /// @param entry_point the SPIR-V ID of an entry point.
    /// @returns the entry point info for the given ID
    const std::vector<EntryPointInfo>& GetEntryPointInfo(uint32_t entry_point) {
        return impl_.GetEntryPointInfo(entry_point);
    }

    /// Returns the handle usage for a memory object declaration.
    /// @param id SPIR-V ID of a sampler or image OpVariable or
    /// OpFunctionParameter
    /// @returns the handle usage, or an empty usage object.
    Usage GetHandleUsage(uint32_t id) const { return impl_.GetHandleUsage(id); }

    /// Returns the SPIR-V instruction with the given ID, or nullptr.
    /// @param id the SPIR-V result ID
    /// @returns the instruction, or nullptr on error
    const spvtools::opt::Instruction* GetInstructionForTest(uint32_t id) const {
        return impl_.GetInstructionForTest(id);
    }

    /// @returns info about the gl_Position builtin variable.
    const ASTParser::BuiltInPositionInfo& GetBuiltInPositionInfo() {
        return impl_.GetBuiltInPositionInfo();
    }

    /// Returns the source record for the SPIR-V instruction with the given
    /// result ID.
    /// @param id the SPIR-V result id.
    /// @return the Source record, or a default one
    Source GetSourceForResultIdForTest(uint32_t id) const {
        return impl_.GetSourceForResultIdForTest(id);
    }

    /// @param resolve if true, the resolver should be run on the program when its build
    void SetResolveOnBuild(bool resolve) { resolve_ = resolve; }

  private:
    ASTParser impl_;
    /// When true, indicates the input SPIR-V module should not be emitted.
    /// It's either deliberately invalid, or not supported for some pending
    /// reason.
    bool skip_dumping_spirv_ = false;
    static bool dump_successfully_converted_spirv_;
    bool resolve_ = true;
};

// Sets global state to force dumping of the assembly text of succesfully
// SPIR-V.
inline void DumpSuccessfullyConvertedSpirv() {
    ASTParserWrapperForTest::DumpSuccessfullyConvertedSpirv();
}

/// Returns the WGSL printed string of a program.
/// @param program the Program
/// @returns the WGSL printed string the program.
std::string ToString(const Program& program);

/// Returns the WGSL printed string of a statement list.
/// @param program the Program
/// @param stmts the statement list
/// @returns the WGSL printed string of a statement list.
std::string ToString(const Program& program, VectorRef<const ast::Statement*> stmts);

/// Returns the WGSL printed string of an AST node.
/// @param program the Program
/// @param node the AST node
/// @returns the WGSL printed string of the AST node.
std::string ToString(const Program& program, const ast::Node* node);

}  // namespace tint::spirv::reader::ast_parser::test

namespace tint::spirv::reader::ast_parser {

/// SPIR-V Parser test class
template <typename T>
class SpirvASTParserTestBase : public T {
  public:
    SpirvASTParserTestBase() = default;
    ~SpirvASTParserTestBase() override = default;

    /// Retrieves the parser from the helper
    /// @param input the SPIR-V binary to parse
    /// @returns a parser for the given binary
    std::unique_ptr<test::ASTParserWrapperForTest> parser(const std::vector<uint32_t>& input) {
        auto parser = std::make_unique<test::ASTParserWrapperForTest>(input);
        // Don't run the Resolver when building the program.
        // We're not interested in type information with these tests.
        parser->SetResolveOnBuild(false);
        return parser;
    }
};

/// SpirvASTParserTest the the base class for SPIR-V reader unit tests.
/// Use this form when you don't need to template any further.
using SpirvASTParserTest = SpirvASTParserTestBase<::testing::Test>;

}  // namespace tint::spirv::reader::ast_parser

#endif  // SRC_TINT_LANG_SPIRV_READER_AST_PARSER_HELPER_TEST_H_
