/*
 *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/ref_counted_object.h"

#include <memory>
#include <string>
#include <type_traits>
#include <utility>

#include "api/scoped_refptr.h"
#include "rtc_base/ref_count.h"
#include "test/gtest.h"

namespace rtc {

namespace {

class A {
 public:
  A() {}

  A(const A&) = delete;
  A& operator=(const A&) = delete;
};

class RefClass : public RefCountInterface {
 public:
  RefClass() {}

 protected:
  ~RefClass() override {}
};

class RefClassWithRvalue : public RefCountInterface {
 public:
  explicit RefClassWithRvalue(std::unique_ptr<A> a) : a_(std::move(a)) {}

 protected:
  ~RefClassWithRvalue() override {}

 public:
  std::unique_ptr<A> a_;
};

class RefClassWithMixedValues : public RefCountInterface {
 public:
  RefClassWithMixedValues(std::unique_ptr<A> a, int b, const std::string& c)
      : a_(std::move(a)), b_(b), c_(c) {}

 protected:
  ~RefClassWithMixedValues() override {}

 public:
  std::unique_ptr<A> a_;
  int b_;
  std::string c_;
};

class Foo {
 public:
  Foo() {}
  Foo(int i, int j) : foo_(i + j) {}
  int foo_ = 0;
};

class FooItf : public RefCountInterface {
 public:
  FooItf() {}
  FooItf(int i, int j) : foo_(i + j) {}
  int foo_ = 0;
};

}  // namespace

TEST(RefCountedObject, HasOneRef) {
  scoped_refptr<RefCountedObject<RefClass>> aref(
      new RefCountedObject<RefClass>());
  EXPECT_TRUE(aref->HasOneRef());
  aref->AddRef();
  EXPECT_FALSE(aref->HasOneRef());
  EXPECT_EQ(aref->Release(), RefCountReleaseStatus::kOtherRefsRemained);
  EXPECT_TRUE(aref->HasOneRef());
}

TEST(RefCountedObject, SupportRValuesInCtor) {
  std::unique_ptr<A> a(new A());
  scoped_refptr<RefClassWithRvalue> ref(
      new RefCountedObject<RefClassWithRvalue>(std::move(a)));
  EXPECT_TRUE(ref->a_.get() != nullptr);
  EXPECT_TRUE(a.get() == nullptr);
}

TEST(RefCountedObject, SupportMixedTypesInCtor) {
  std::unique_ptr<A> a(new A());
  int b = 9;
  std::string c = "hello";
  scoped_refptr<RefClassWithMixedValues> ref(
      new RefCountedObject<RefClassWithMixedValues>(std::move(a), b, c));
  EXPECT_TRUE(ref->a_.get() != nullptr);
  EXPECT_TRUE(a.get() == nullptr);
  EXPECT_EQ(b, ref->b_);
  EXPECT_EQ(c, ref->c_);
}

TEST(FinalRefCountedObject, CanWrapIntoScopedRefptr) {
  using WrappedTyped = FinalRefCountedObject<A>;
  static_assert(!std::is_polymorphic<WrappedTyped>::value, "");
  scoped_refptr<WrappedTyped> ref(new WrappedTyped());
  EXPECT_TRUE(ref.get());
  EXPECT_TRUE(ref->HasOneRef());
  // Test reference counter is updated on some simple operations.
  scoped_refptr<WrappedTyped> ref2 = ref;
  EXPECT_FALSE(ref->HasOneRef());
  EXPECT_FALSE(ref2->HasOneRef());

  ref = nullptr;
  EXPECT_TRUE(ref2->HasOneRef());
}

TEST(FinalRefCountedObject, CanCreateFromMovedType) {
  class MoveOnly {
   public:
    MoveOnly(int a) : a_(a) {}
    MoveOnly(MoveOnly&&) = default;

    int a() { return a_; }

   private:
    int a_;
  };
  MoveOnly foo(5);
  auto ref = make_ref_counted<MoveOnly>(std::move(foo));
  EXPECT_EQ(ref->a(), 5);
}

// This test is mostly a compile-time test for scoped_refptr compatibility.
TEST(RefCounted, SmartPointers) {
  // Sanity compile-time tests. FooItf is virtual, Foo is not, FooItf inherits
  // from RefCountInterface, Foo does not.
  static_assert(std::is_base_of<RefCountInterface, FooItf>::value, "");
  static_assert(!std::is_base_of<RefCountInterface, Foo>::value, "");
  static_assert(std::is_polymorphic<FooItf>::value, "");
  static_assert(!std::is_polymorphic<Foo>::value, "");

  // Check if Ref generates the expected types for Foo and FooItf.
  static_assert(std::is_base_of<Foo, Ref<Foo>::Type>::value &&
                    !std::is_same<Foo, Ref<Foo>::Type>::value,
                "");
  static_assert(std::is_same<FooItf, Ref<FooItf>::Type>::value, "");

  {
    // Test with FooItf, a class that inherits from RefCountInterface.
    // Check that we get a valid FooItf reference counted object.
    auto p = make_ref_counted<FooItf>(2, 3);
    EXPECT_NE(p.get(), nullptr);
    EXPECT_EQ(p->foo_, 5);  // the FooItf ctor just stores 2+3 in foo_.

    // Use a couple of different ways of declaring what should result in the
    // same type as `p` is of.
    scoped_refptr<Ref<FooItf>::Type> p2 = p;
    Ref<FooItf>::Ptr p3 = p;
  }

  {
    // Same for `Foo`
    auto p = make_ref_counted<Foo>(2, 3);
    EXPECT_NE(p.get(), nullptr);
    EXPECT_EQ(p->foo_, 5);
    scoped_refptr<Ref<Foo>::Type> p2 = p;
    Ref<Foo>::Ptr p3 = p;
  }
}

}  // namespace rtc
