// Copyright 2020 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 <unordered_set>

#include "gtest/gtest.h"
#include "src/ast/case_statement.h"
#include "src/demangler.h"
#include "src/reader/wgsl/parser.h"
#include "src/writer/wgsl/generator.h"

namespace tint {
namespace ast {
namespace {

TEST(ModuleCloneTest, Clone) {
#if TINT_BUILD_WGSL_READER && TINT_BUILD_WGSL_WRITER
  // Shader that exercises the bulk of the AST nodes and types.
  // See also fuzzers/tint_ast_clone_fuzzer.cc for further coverage of cloning.
  Source::File file("test.wgsl", R"([[block]]
struct S {
  [[offset(0)]]
  m0 : u32;
  [[offset(4)]]
  m1 : array<u32>;
};

type t0 = [[stride(16)]] array<vec4<f32>>;
type t1 = [[stride(32)]] array<vec4<f32>>;

const c0 : i32 = 10;
const c1 : bool = true;

var<uniform> g0 : u32 = 20u;
var<out> g1 : f32 = 123.0;
var<uniform> g2 : texture_2d<f32>;
var<uniform> g3 : [[access(read)]] texture_storage_2d<r32uint>;
var<uniform> g4 : [[access(write)]] texture_storage_2d<rg32float>;
var<uniform> g5 : [[access(read)]] texture_storage_2d<r32uint>;
var<uniform> g6 : [[access(write)]] texture_storage_2d<rg32float>;

[[builtin(position)]] var<uniform> g7 : vec3<f32>;
[[group(10), binding(20)]] var<storage_buffer> g7 : S;
[[group(10), binding(20)]] var<storage_buffer> g8 : [[access(read)]]
S;
[[group(10), binding(20)]] var<storage_buffer> g9 : [[access(read_write)]]
S;

fn f0(p0 : bool) -> f32 {
  if (p0) {
    return 1.0;
  }
  return 0.0;
}

fn f1(p0 : f32, p1 : i32) -> f32 {
  var l0 : i32 = 3;
  var l1 : f32 = 8;
  var l2 : u32 = bitcast<u32>(4);
  var l3 : vec2<u32> = vec2<u32>(l0, l1);
  var l4 : S;
  var l5 : u32 = l4.m1[5];
  var l6 : ptr<private, u32>;
  l6 = null;
  loop {
    l0 = (p1 + 2);
    if (((l0 % 4) == 0)) {
      continue;
    }

    continuing {
      if (1 == 2) {
        l0 = l0 - 1;
      } else {
        l0 = l0 - 2;
      }
    }
  }
  switch(l2) {
    case 0: {
      break;
    }
    case 1: {
      return f0(true);
    }
    default: {
      discard;
    }
  }
  return 1.0;
}

[[stage(fragment)]]
fn main() -> void {
  f1(1.0, 2);
}

)");

  // Parse the wgsl, create the src module
  reader::wgsl::Parser parser(&file);
  ASSERT_TRUE(parser.Parse()) << parser.error();
  auto src = parser.module();

  // Clone the src module to dst
  auto dst = src.Clone();

  // Expect the AST printed with to_str() to match
  Demangler demanger;
  EXPECT_EQ(demanger.Demangle(src, src.to_str()),
            demanger.Demangle(dst, dst.to_str()));

  // Check that none of the AST nodes or type pointers in dst are found in src
  std::unordered_set<ast::Node*> src_nodes;
  for (auto& src_node : src.nodes()) {
    src_nodes.emplace(src_node.get());
  }
  std::unordered_set<ast::type::Type*> src_types;
  for (auto& src_type : src.types()) {
    src_types.emplace(src_type.second.get());
  }
  for (auto& dst_node : dst.nodes()) {
    ASSERT_EQ(src_nodes.count(dst_node.get()), 0u) << dst_node->str();
  }
  for (auto& dst_type : dst.types()) {
    ASSERT_EQ(src_types.count(dst_type.second.get()), 0u)
        << dst_type.second->type_name();
  }

  // Regenerate the wgsl for the src module. We use this instead of the original
  // source so that reformatting doesn't impact the final wgsl comparision.
  // Note that the src module is moved into the generator and this generator has
  // a limited scope, so that the src module is released before we attempt to
  // print the dst module.
  // This guarantee that all the source module nodes and types are destructed
  // and freed.
  // ASAN should error if there's any remaining references in dst when we try to
  // reconstruct the WGSL.
  std::string src_wgsl;
  {
    writer::wgsl::Generator src_gen(std::move(src));
    ASSERT_TRUE(src_gen.Generate()) << src_gen.error();
    src_wgsl = src_gen.result();
  }

  // Print the dst module, check it matches the original source
  writer::wgsl::Generator dst_gen(std::move(dst));
  ASSERT_TRUE(dst_gen.Generate());
  auto dst_wgsl = dst_gen.result();
  ASSERT_EQ(src_wgsl, dst_wgsl);

#else  // #if TINT_BUILD_WGSL_READER && TINT_BUILD_WGSL_WRITER
  GTEST_SKIP() << "ModuleCloneTest requires TINT_BUILD_WGSL_READER and "
                  "TINT_BUILD_WGSL_WRITER to be enabled";
#endif
}

}  // namespace
}  // namespace ast
}  // namespace tint
