// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "lib/fidl-async-2/fidl_struct.h"

#include <inttypes.h>
#include <lib/fidl/llcpp/heap_allocator.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/zx/event.h>

#include <type_traits>

#include <fidl/types/test/c/fidl.h>
#include <fidl/types/test/llcpp/fidl.h>
#include <zxtest/zxtest.h>

namespace {

template <typename C, typename Enable = void>
struct HasCopyAsLlcpp : std::false_type {};
template <typename C>
struct HasCopyAsLlcpp<
    C, typename std::enable_if<std::is_same<decltype(std::declval<C>().CopyAsLlcpp()),
                                            typename C::llcpp_type>::value>::type>
    : std::true_type {};

}  // namespace

using namespace ::llcpp::fidl::types::test;

TEST(FidlStruct, CopyableStruct) {
  constexpr int32_t kNewFieldValue = 12;
  using Struct = FidlStruct<fidl_types_test_CopyableStruct, CopyableStruct>;
  Struct s(Struct::Default);
  const Struct& sc = s;
  EXPECT_EQ(0, s->x);
  s->x = kNewFieldValue;
  EXPECT_EQ(kNewFieldValue, s->x);
  static_assert(HasCopyAsLlcpp<Struct>::value);
  EXPECT_EQ(kNewFieldValue, s.CopyAsLlcpp().x);
  EXPECT_EQ(kNewFieldValue, s.BorrowAsLlcpp().x);
  EXPECT_EQ(kNewFieldValue, sc.BorrowAsLlcpp().x);
  fidl_types_test_CopyableStruct* ps = s.get();
  const fidl_types_test_CopyableStruct* cps = s.get();
  EXPECT_EQ(kNewFieldValue, ps->x);
  EXPECT_EQ(kNewFieldValue, cps->x);
  EXPECT_EQ(kNewFieldValue, Struct::BorrowAsLlcpp(ps)->x);
  EXPECT_EQ(kNewFieldValue, Struct::BorrowAsLlcpp(cps)->x);
  EXPECT_EQ(kNewFieldValue, s.TakeAsLlcpp().x);
  // TakeAsLlcpp() moved it out.
  EXPECT_FALSE(!!s);
}

TEST(FidlStruct, MoveOnlyStruct) {
  zx::event event;
  zx::event::create(0, &event);
  zx::handle h(event.release());
  int32_t new_field_value = h.get();
  using Struct = FidlStruct<fidl_types_test_MoveOnlyStruct, MoveOnlyStruct>;
  Struct s(Struct::Default);
  const Struct& sc = s;
  EXPECT_EQ(ZX_HANDLE_INVALID, s->h);
  s->h = h.release();
  EXPECT_EQ(new_field_value, s->h);
  static_assert(!HasCopyAsLlcpp<Struct>::value);
  EXPECT_EQ(new_field_value, s.BorrowAsLlcpp().h);
  EXPECT_EQ(new_field_value, sc.BorrowAsLlcpp().h);
  fidl_types_test_MoveOnlyStruct* ps = s.get();
  const fidl_types_test_MoveOnlyStruct* cps = s.get();
  EXPECT_EQ(new_field_value, ps->h);
  EXPECT_EQ(new_field_value, cps->h);
  EXPECT_EQ(new_field_value, Struct::BorrowAsLlcpp(ps)->h);
  EXPECT_EQ(new_field_value, Struct::BorrowAsLlcpp(cps)->h);
  EXPECT_EQ(new_field_value, s.TakeAsLlcpp().h);
  // TakeAsLlcpp() moved it out.
  EXPECT_FALSE(!!s);
}

TEST(FidlStruct, StructWithArrays) {
  constexpr int32_t kNewFieldValue = 12;
  using Struct = FidlStruct<fidl_types_test_StructWithArrays, StructWithArrays>;
  Struct s(Struct::Default);
  const Struct& sc = s;
  EXPECT_EQ(0, s->x);
  s->x = kNewFieldValue;
  EXPECT_EQ(kNewFieldValue, s->x);
  static_assert(HasCopyAsLlcpp<Struct>::value);
  EXPECT_EQ(kNewFieldValue, s.CopyAsLlcpp().x);
  EXPECT_EQ(kNewFieldValue, s.BorrowAsLlcpp().x);
  EXPECT_EQ(kNewFieldValue, sc.BorrowAsLlcpp().x);
  fidl_types_test_StructWithArrays* ps = s.get();
  const fidl_types_test_StructWithArrays* cps = s.get();
  EXPECT_EQ(kNewFieldValue, ps->x);
  EXPECT_EQ(kNewFieldValue, cps->x);
  EXPECT_EQ(kNewFieldValue, Struct::BorrowAsLlcpp(ps)->x);
  EXPECT_EQ(kNewFieldValue, Struct::BorrowAsLlcpp(cps)->x);
  EXPECT_EQ(kNewFieldValue, s.TakeAsLlcpp().x);
  // TakeAsLlcpp() moved it out.
  EXPECT_FALSE(!!s);
}

TEST(FidlStruct, StructWithSubStruct) {
  constexpr int32_t kNewFieldValue = 12;
  using Struct = FidlStruct<fidl_types_test_StructWithSubStruct, StructWithSubStruct>;
  Struct s(Struct::Default);
  const Struct& sc = s;
  EXPECT_EQ(0, s->s.x);
  s->s.x = kNewFieldValue;
  EXPECT_EQ(kNewFieldValue, s->s.x);
  static_assert(HasCopyAsLlcpp<Struct>::value);
  EXPECT_EQ(kNewFieldValue, s.CopyAsLlcpp().s.x);
  EXPECT_EQ(kNewFieldValue, s.BorrowAsLlcpp().s.x);
  EXPECT_EQ(kNewFieldValue, sc.BorrowAsLlcpp().s.x);
  fidl_types_test_StructWithSubStruct* ps = s.get();
  const fidl_types_test_StructWithSubStruct* cps = s.get();
  EXPECT_EQ(kNewFieldValue, ps->s.x);
  EXPECT_EQ(kNewFieldValue, cps->s.x);
  EXPECT_EQ(kNewFieldValue, Struct::BorrowAsLlcpp(ps)->s.x);
  EXPECT_EQ(kNewFieldValue, Struct::BorrowAsLlcpp(cps)->s.x);
  EXPECT_EQ(kNewFieldValue, s.TakeAsLlcpp().s.x);
  // TakeAsLlcpp() moved it out.
  EXPECT_FALSE(!!s);
}

TEST(FidlStruct, EmptyStruct) {
  using Struct = FidlStruct<fidl_types_test_EmptyStruct, EmptyStruct>;
  Struct s(Struct::Default);
  const Struct& sc = s;
  static_assert(HasCopyAsLlcpp<Struct>::value);
  (void)s.CopyAsLlcpp();
  (void)s.BorrowAsLlcpp();
  (void)sc.BorrowAsLlcpp();
  fidl_types_test_EmptyStruct* ps = s.get();
  const fidl_types_test_EmptyStruct* cps = s.get();
  (void)Struct::BorrowAsLlcpp(ps);
  (void)Struct::BorrowAsLlcpp(cps);
  (void)s.TakeAsLlcpp();
  // TakeAsLlcpp() moved it out.
  EXPECT_FALSE(!!s);
}

// If this builds, it passes.
TEST(FidlStruct, TypeAliases) {
  using Struct = FidlStruct<fidl_types_test_EmptyStruct, EmptyStruct>;
  static_assert(std::is_same<Struct::c_type, fidl_types_test_EmptyStruct>::value);
  static_assert(std::is_same<Struct::llcpp_type, EmptyStruct>::value);
}
