// Copyright 2017 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 "src/ui/lib/escher/base/ownable.h"

#include <gtest/gtest.h>

#include "src/lib/fxl/memory/ref_ptr.h"
#include "src/ui/lib/escher/base/owner.h"
#include "src/ui/lib/escher/base/type_info.h"

namespace {

enum class OwnableTypes {
  kOwnableBaseClassForTest = 1,
  kOwnable1 = 1 << 1,
  kOwnable2 = 1 << 2,
  kSubOwnable1 = 1 << 3,
  kSubOwnable2 = 1 << 4,
};

typedef escher::TypeInfo<OwnableTypes> OwnableTypeInfo;

class OwnableBaseClassForTest : public escher::Ownable<OwnableBaseClassForTest, OwnableTypeInfo> {
 public:
  static const TypeInfo kTypeInfo;
  const TypeInfo& type_info() const override { return OwnableBaseClassForTest::kTypeInfo; }

  using escher::Ownable<OwnableBaseClassForTest, OwnableTypeInfo>::owner;
};

class Ownable1 : public OwnableBaseClassForTest {
 public:
  static const TypeInfo kTypeInfo;
  const TypeInfo& type_info() const override { return Ownable1::kTypeInfo; }

  explicit Ownable1(size_t& destroyed_count) : destroyed_count_(destroyed_count) {}

  ~Ownable1() override { ++destroyed_count_; }

 private:
  size_t& destroyed_count_;
};

class Ownable2 : public OwnableBaseClassForTest {
 public:
  static const TypeInfo kTypeInfo;
  const TypeInfo& type_info() const override { return Ownable2::kTypeInfo; }
};

class SubOwnable1 : public Ownable1 {
 public:
  static const TypeInfo kTypeInfo;
  const TypeInfo& type_info() const override { return SubOwnable1::kTypeInfo; }

  explicit SubOwnable1(size_t& destroyed_count) : Ownable1(destroyed_count) {}
};

class SubOwnable2 : public Ownable2 {
 public:
  static const TypeInfo kTypeInfo;
  const TypeInfo& type_info() const override { return SubOwnable2::kTypeInfo; }
};

const OwnableTypeInfo OwnableBaseClassForTest::kTypeInfo("OwnableBaseClassForTest",
                                                         OwnableTypes::kOwnableBaseClassForTest);
const OwnableTypeInfo Ownable1::kTypeInfo("Ownable1", OwnableTypes::kOwnableBaseClassForTest,
                                          OwnableTypes::kOwnable1);
const OwnableTypeInfo Ownable2::kTypeInfo("Ownable2", OwnableTypes::kOwnableBaseClassForTest,
                                          OwnableTypes::kOwnable2);
const OwnableTypeInfo SubOwnable1::kTypeInfo("SubOwnable1", OwnableTypes::kOwnableBaseClassForTest,
                                             OwnableTypes::kOwnable1, OwnableTypes::kSubOwnable1);
const OwnableTypeInfo SubOwnable2::kTypeInfo("SubOwnable2", OwnableTypes::kOwnableBaseClassForTest,
                                             OwnableTypes::kOwnable2, OwnableTypes::kSubOwnable2);

class TestOwner : public escher::Owner<OwnableBaseClassForTest, OwnableTypeInfo> {
 public:
  explicit TestOwner(size_t& destroyed_count) : destroyed_count_(destroyed_count) {}

  fxl::RefPtr<Ownable1> NewOwnable1() {
    auto result = escher::Make<Ownable1>(destroyed_count_);
    EXPECT_EQ(1U, result->ref_count());
    BecomeOwnerOf(result.get());
    return result;
  }

  void OnReceiveOwnable(std::unique_ptr<OwnableBaseClassForTest> unreffed) override {
    EXPECT_EQ(0U, unreffed->ref_count());
    unreffed_.push_back(fxl::RefPtr<OwnableBaseClassForTest>(unreffed.release()));
  }

  size_t GetUnreffedCount() const { return unreffed_.size(); }
  void ClearUnreffed() {
    for (auto& owned : unreffed_) {
      // So that they are destroyed.
      RelinquishOwnershipOf(owned.get());
    }
    unreffed_.clear();
  }

 private:
  size_t& destroyed_count_;
  std::vector<fxl::RefPtr<OwnableBaseClassForTest>> unreffed_;
};

TEST(Ownable, ReceiveOwnables) {
  size_t destroyed_count = 0;
  auto owner = std::make_unique<TestOwner>(destroyed_count);
  EXPECT_EQ(0U, owner->ownable_count());

  auto ownable1 = owner->NewOwnable1();
  auto ownable2 = owner->NewOwnable1();
  EXPECT_EQ(ownable1->owner(), owner.get());
  EXPECT_EQ(ownable2->owner(), owner.get());
  EXPECT_EQ(2U, owner->ownable_count());
  EXPECT_EQ(0U, owner->GetUnreffedCount());
  EXPECT_EQ(0U, destroyed_count);
  EXPECT_NE(ownable1.get(), ownable2.get());

  ownable1 = ownable2;
  EXPECT_EQ(ownable1.get(), ownable2.get());
  EXPECT_EQ(2U, ownable1->ref_count());
  EXPECT_EQ(2U, owner->ownable_count());
  EXPECT_EQ(1U, owner->GetUnreffedCount());
  EXPECT_EQ(0U, destroyed_count);

  owner->ClearUnreffed();
  EXPECT_EQ(1U, owner->ownable_count());
  EXPECT_EQ(0U, owner->GetUnreffedCount());
  EXPECT_EQ(1U, destroyed_count);

  ownable2 = nullptr;
  EXPECT_EQ(1U, owner->ownable_count());
  EXPECT_EQ(0U, owner->GetUnreffedCount());
  EXPECT_EQ(1U, destroyed_count);

  ownable1 = nullptr;
  EXPECT_EQ(1U, owner->ownable_count());
  EXPECT_EQ(1U, owner->GetUnreffedCount());
  EXPECT_EQ(1U, destroyed_count);

  owner->ClearUnreffed();
  EXPECT_EQ(0U, owner->ownable_count());
  EXPECT_EQ(0U, owner->GetUnreffedCount());
  EXPECT_EQ(2U, destroyed_count);
}

}  // namespace
