1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
/**
* Copyright 2020-2024, XGBoost contributors
*/
#include <gtest/gtest.h>
#include <xgboost/intrusive_ptr.h>
namespace xgboost {
namespace {
class NotCopyConstructible {
public:
float data;
explicit NotCopyConstructible(float d) : data{d} {}
NotCopyConstructible(NotCopyConstructible const &that) = delete;
NotCopyConstructible &operator=(NotCopyConstructible const &that) = delete;
NotCopyConstructible(NotCopyConstructible&& that) = default;
};
static_assert(!std::is_trivially_copy_constructible_v<NotCopyConstructible>);
static_assert(!std::is_trivially_copy_assignable_v<NotCopyConstructible>);
class ForIntrusivePtrTest {
public:
mutable class IntrusivePtrCell ref;
float data { 0 };
friend IntrusivePtrCell &
IntrusivePtrRefCount(ForIntrusivePtrTest const *t) noexcept { // NOLINT
return t->ref;
}
ForIntrusivePtrTest() = default;
ForIntrusivePtrTest(float a, int32_t b) : data{a + static_cast<float>(b)} {}
explicit ForIntrusivePtrTest(NotCopyConstructible a) : data{a.data} {}
};
} // anonymous namespace
TEST(IntrusivePtr, Basic) {
IntrusivePtr<ForIntrusivePtrTest> ptr {new ForIntrusivePtrTest};
auto p = ptr.get();
// Copy ctor
IntrusivePtr<ForIntrusivePtrTest> ptr_1 { ptr };
ASSERT_EQ(ptr_1.get(), p);
ASSERT_EQ((*ptr_1).data, ptr_1->data);
ASSERT_EQ(ptr.use_count(), 2);
// hash
ASSERT_EQ(std::hash<IntrusivePtr<ForIntrusivePtrTest>>{}(ptr_1),
std::hash<ForIntrusivePtrTest*>{}(ptr_1.get()));
// Raw ptr comparison
ASSERT_EQ(ptr, p);
ASSERT_EQ(ptr_1, ptr);
ForIntrusivePtrTest* raw_ptr {nullptr};
ASSERT_NE(ptr_1, raw_ptr);
ASSERT_NE(raw_ptr, ptr_1);
// Reset with raw ptr.
auto p_1 = new ForIntrusivePtrTest;
ptr.reset(p_1);
ASSERT_EQ(ptr_1.use_count(), 1);
ASSERT_EQ(ptr.use_count(), 1);
ASSERT_TRUE(ptr);
ASSERT_TRUE(ptr_1);
// Swap
std::swap(ptr, ptr_1);
ASSERT_NE(ptr, p_1);
ASSERT_EQ(ptr_1, p_1);
// Reset
ptr.reset();
ASSERT_FALSE(ptr);
ASSERT_EQ(ptr.use_count(), 0);
// Comparison operators
ASSERT_EQ(ptr < ptr_1, ptr.get() < ptr_1.get());
ASSERT_EQ(ptr > ptr_1, ptr.get() > ptr_1.get());
ASSERT_LE(ptr, ptr);
ASSERT_GE(ptr, ptr);
// Copy assign
IntrusivePtr<ForIntrusivePtrTest> ptr_2;
ptr_2 = ptr_1;
ASSERT_EQ(ptr_2, ptr_1);
ASSERT_EQ(ptr_2.use_count(), 2);
// Move assign
IntrusivePtr<ForIntrusivePtrTest> ptr_3;
ptr_3 = std::move(ptr_2);
ASSERT_EQ(ptr_2.use_count(), 0); // NOLINT
ASSERT_EQ(ptr_3.use_count(), 2);
// Move ctor
IntrusivePtr<ForIntrusivePtrTest> ptr_4 { std::move(ptr_3) };
ASSERT_EQ(ptr_3.use_count(), 0); // NOLINT
ASSERT_EQ(ptr_4.use_count(), 2);
// Comparison
ASSERT_EQ(ptr_1 > ptr_2, ptr_1.get() > ptr_2.get());
ASSERT_EQ(ptr_1, ptr_1);
ASSERT_EQ(ptr_1 < ptr_2, ptr_1.get() < ptr_2.get());
}
} // namespace xgboost
|