1 // 2 // Tests for 3 // template <typename U> 4 // intrusive_shared_ptr(intrusive_shared_ptr<U, RefcountPolicy>&& other); 5 // 6 // intrusive_shared_ptr(intrusive_shared_ptr&& other); 7 // 8 9 #include <libkern/c++/intrusive_shared_ptr.h> 10 #include <darwintest.h> 11 #include <darwintest_utils.h> 12 #include <type_traits> 13 #include <utility> 14 #include "test_policy.h" 15 16 struct Base { int i; }; 17 struct Derived : Base { }; 18 19 struct Base1 { int i; }; 20 struct Base2 { long l; }; 21 struct DerivedMultiple : Base1, Base2 { 22 DerivedMultiple(int i) : Base1{i}, Base2{i + 10} 23 { 24 } 25 }; 26 27 struct Unrelated { }; 28 29 template <typename Stored, typename From, typename To> 30 static void 31 tests() 32 { 33 Stored obj{3}; 34 35 // Test with non-null pointers 36 { 37 test_policy::retain_count = 0; 38 libkern::intrusive_shared_ptr<From, test_policy> from(&obj, libkern::retain); 39 CHECK(test_policy::retain_count == 1); 40 CHECK(from.get() == &obj); 41 42 libkern::intrusive_shared_ptr<To, test_policy> to(std::move(from)); // explicit 43 CHECK(test_policy::retain_count == 1); 44 CHECK(to.get() == &obj); 45 CHECK(from.get() == nullptr); 46 } 47 { 48 test_policy::retain_count = 0; 49 libkern::intrusive_shared_ptr<From, test_policy> from(&obj, libkern::retain); 50 CHECK(test_policy::retain_count == 1); 51 CHECK(from.get() == &obj); 52 53 libkern::intrusive_shared_ptr<To, test_policy> to{std::move(from)}; // explicit 54 CHECK(test_policy::retain_count == 1); 55 CHECK(to.get() == &obj); 56 CHECK(from.get() == nullptr); 57 } 58 { 59 test_policy::retain_count = 0; 60 libkern::intrusive_shared_ptr<From, test_policy> from(&obj, libkern::retain); 61 CHECK(test_policy::retain_count == 1); 62 CHECK(from.get() == &obj); 63 64 libkern::intrusive_shared_ptr<To, test_policy> to = std::move(from); // implicit 65 CHECK(test_policy::retain_count == 1); 66 CHECK(to.get() == &obj); 67 CHECK(from.get() == nullptr); 68 } 69 70 // Test with a null pointer 71 { 72 test_policy::retain_count = 3; 73 libkern::intrusive_shared_ptr<From, test_policy> from = nullptr; 74 libkern::intrusive_shared_ptr<To, test_policy> to = std::move(from); 75 CHECK(test_policy::retain_count == 3); 76 CHECK(to.get() == nullptr); 77 CHECK(from.get() == nullptr); 78 } 79 } 80 81 T_DECL(ctor_move, "intrusive_shared_ptr.ctor.move") { 82 tests</*stored*/ Derived, /*from*/ Derived, /*to*/ Derived>(); 83 tests</*stored*/ Derived, /*from*/ Derived, /*to*/ Derived const>(); 84 tests</*stored*/ Derived, /*from*/ Derived const, /*to*/ Derived const>(); 85 86 tests</*stored*/ Derived, /*from*/ Derived, /*to*/ Base>(); 87 tests</*stored*/ Derived, /*from*/ Derived, /*to*/ Base const>(); 88 tests</*stored*/ Derived, /*from*/ Derived const, /*to*/ Base const>(); 89 90 tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple, /*to*/ Base1>(); 91 tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple const, /*to*/ Base1 const>(); 92 93 tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple, /*to*/ Base2>(); 94 tests</*stored*/ DerivedMultiple, /*from*/ DerivedMultiple const, /*to*/ Base2 const>(); 95 96 // Make sure basic trait querying works 97 static_assert(std::is_move_constructible_v<test_shared_ptr<Derived> >); 98 99 // Make sure downcasts are disabled 100 static_assert(!std::is_constructible_v</*to*/ test_shared_ptr<Derived>, /*from*/ test_shared_ptr<Base>&&>); 101 static_assert(!std::is_constructible_v</*to*/ test_shared_ptr<DerivedMultiple>, /*from*/ test_shared_ptr<Base1>&&>); 102 static_assert(!std::is_constructible_v</*to*/ test_shared_ptr<DerivedMultiple>, /*from*/ test_shared_ptr<Base2>&&>); 103 static_assert(!std::is_constructible_v</*to*/ test_shared_ptr<Base2>, /*from*/ test_shared_ptr<Base1>&&>); 104 105 // Make sure const-casting away doesn't work 106 static_assert(!std::is_constructible_v</*to*/ test_shared_ptr<Derived>, /*from*/ test_shared_ptr<Derived const>&&>); 107 108 // Make sure casting to unrelated types doesn't work 109 static_assert(!std::is_constructible_v</*to*/ test_shared_ptr<char>, /*from*/ test_shared_ptr<Derived>&&>); 110 static_assert(!std::is_constructible_v</*to*/ test_shared_ptr<Unrelated>, /*from*/ test_shared_ptr<Derived>&&>); 111 static_assert(!std::is_constructible_v</*to*/ test_shared_ptr<Base2>, /*from*/ test_shared_ptr<Base1>&&>); 112 113 // Make sure constructing with different policies doesn't work 114 static_assert(!std::is_constructible_v</*to*/ libkern::intrusive_shared_ptr<Derived, dummy_policy<2> >, /*from*/ libkern::intrusive_shared_ptr<Derived, dummy_policy<1> >&&>); 115 } 116