]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/common/test_static_ptr.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / common / test_static_ptr.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2017 Red Hat, Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include <compare>
16 #include <gtest/gtest.h>
17 #include "common/static_ptr.h"
18
19 using ceph::static_ptr;
20 using ceph::make_static;
21
22 class base {
23 public:
24 virtual int func() = 0;
25 virtual ~base() = default;
26 };
27
28 class sibling1 : public base {
29 public:
30 int func() override { return 0; }
31 };
32
33 class sibling2 : public base {
34 public:
35 int func() override { return 9; }
36 virtual int call(int) = 0;
37 };
38
39 class grandchild : public sibling2 {
40 protected:
41 int val;
42 public:
43 explicit grandchild(int val) : val(val) {}
44 virtual int call(int n) override { return n * val; }
45 };
46
47 class great_grandchild : public grandchild {
48 public:
49 explicit great_grandchild(int val) : grandchild(val) {}
50 int call(int n) override { return n + val; }
51 };
52
53 #ifdef __cpp_lib_three_way_comparison
54 TEST(StaticPtr, EmptyCreation) {
55 static_ptr<base, sizeof(grandchild)> p;
56 EXPECT_FALSE(p);
57 EXPECT_EQ(p, nullptr);
58 EXPECT_EQ(nullptr, p);
59 EXPECT_TRUE(p.get() == nullptr);
60 }
61
62 TEST(StaticPtr, CreationCall) {
63 {
64 static_ptr<base, sizeof(grandchild)> p(std::in_place_type_t<sibling1>{});
65 EXPECT_TRUE(p);
66 EXPECT_FALSE(p == nullptr);
67 EXPECT_FALSE(nullptr == p);
68 EXPECT_FALSE(p.get() == nullptr);
69 EXPECT_EQ(p->func(), 0);
70 EXPECT_EQ((*p).func(), 0);
71 EXPECT_EQ((p.get())->func(), 0);
72 }
73 {
74 auto p = make_static<base, sibling1>();
75 EXPECT_TRUE(p);
76 EXPECT_FALSE(p == nullptr);
77 EXPECT_FALSE(nullptr == p);
78 EXPECT_FALSE(p.get() == nullptr);
79 EXPECT_EQ(p->func(), 0);
80 EXPECT_EQ((*p).func(), 0);
81 EXPECT_EQ((p.get())->func(), 0);
82 }
83 }
84
85 TEST(StaticPtr, CreateReset) {
86 {
87 static_ptr<base, sizeof(grandchild)> p(std::in_place_type_t<sibling1>{});
88 EXPECT_EQ((p.get())->func(), 0);
89 p.reset();
90 EXPECT_FALSE(p);
91 EXPECT_EQ(p, nullptr);
92 EXPECT_EQ(nullptr, p);
93 EXPECT_TRUE(p.get() == nullptr);
94 }
95 {
96 static_ptr<base, sizeof(grandchild)> p(std::in_place_type_t<sibling1>{});
97 EXPECT_EQ((p.get())->func(), 0);
98 p = nullptr;
99 EXPECT_FALSE(p);
100 EXPECT_EQ(p, nullptr);
101 EXPECT_EQ(nullptr, p);
102 EXPECT_TRUE(p.get() == nullptr);
103 }
104 }
105 #endif // __cpp_lib_three_way_comparison
106
107 TEST(StaticPtr, CreateEmplace) {
108 static_ptr<base, sizeof(grandchild)> p(std::in_place_type_t<sibling1>{});
109 EXPECT_EQ((p.get())->func(), 0);
110 p.emplace<grandchild>(30);
111 EXPECT_EQ(p->func(), 9);
112 }
113
114 TEST(StaticPtr, Move) {
115 // Won't compile. Good.
116 // static_ptr<base, sizeof(base)> p1(std::in_place_type_t<grandchild>{}, 3);
117
118 static_ptr<base, sizeof(base)> p1(std::in_place_type_t<sibling1>{});
119 static_ptr<base, sizeof(grandchild)> p2(std::in_place_type_t<grandchild>{},
120 3);
121
122 p2 = std::move(p1);
123 EXPECT_EQ(p1->func(), 0);
124 }
125
126 TEST(StaticPtr, ImplicitUpcast) {
127 static_ptr<base, sizeof(grandchild)> p1;
128 static_ptr<sibling2, sizeof(grandchild)> p2(std::in_place_type_t<grandchild>{}, 3);
129
130 p1 = std::move(p2);
131 EXPECT_EQ(p1->func(), 9);
132
133 p2.reset();
134
135 // Doesn't compile. Good.
136 // p2 = p1;
137 }
138
139 TEST(StaticPtr, StaticCast) {
140 static_ptr<base, sizeof(grandchild)> p1(std::in_place_type_t<grandchild>{}, 3);
141 static_ptr<sibling2, sizeof(grandchild)> p2;
142
143 p2 = ceph::static_pointer_cast<sibling2, sizeof(grandchild)>(std::move(p1));
144 EXPECT_EQ(p2->func(), 9);
145 EXPECT_EQ(p2->call(10), 30);
146 }
147
148 TEST(StaticPtr, DynamicCast) {
149 static constexpr auto sz = sizeof(great_grandchild);
150 {
151 static_ptr<base, sz> p1(std::in_place_type_t<grandchild>{}, 3);
152 auto p2 = ceph::dynamic_pointer_cast<great_grandchild, sz>(std::move(p1));
153 EXPECT_FALSE(p2);
154 }
155
156 {
157 static_ptr<base, sz> p1(std::in_place_type_t<grandchild>{}, 3);
158 auto p2 = ceph::dynamic_pointer_cast<grandchild, sz>(std::move(p1));
159 EXPECT_TRUE(p2);
160 EXPECT_EQ(p2->func(), 9);
161 EXPECT_EQ(p2->call(10), 30);
162 }
163 }
164
165 class constable {
166 public:
167 int foo() {
168 return 2;
169 }
170 int foo() const {
171 return 5;
172 }
173 };
174
175 TEST(StaticPtr, ConstCast) {
176 static constexpr auto sz = sizeof(constable);
177 {
178 auto p1 = make_static<const constable>();
179 EXPECT_EQ(p1->foo(), 5);
180 auto p2 = ceph::const_pointer_cast<constable, sz>(std::move(p1));
181 static_assert(!std::is_const<decltype(p2)::element_type>{},
182 "Things are more const than they ought to be.");
183 EXPECT_TRUE(p2);
184 EXPECT_EQ(p2->foo(), 2);
185 }
186 }
187
188 TEST(StaticPtr, ReinterpretCast) {
189 static constexpr auto sz = sizeof(grandchild);
190 {
191 auto p1 = make_static<grandchild>(3);
192 auto p2 = ceph::reinterpret_pointer_cast<constable, sz>(std::move(p1));
193 static_assert(std::is_same<decltype(p2)::element_type, constable>{},
194 "Reinterpret is screwy.");
195 auto p3 = ceph::reinterpret_pointer_cast<grandchild, sz>(std::move(p2));
196 static_assert(std::is_same<decltype(p3)::element_type, grandchild>{},
197 "Reinterpret is screwy.");
198 EXPECT_EQ(p3->func(), 9);
199 EXPECT_EQ(p3->call(10), 30);
200 }
201 }
202
203 struct exceptional {
204 exceptional() = default;
205 exceptional(const exceptional& e) {
206 throw std::exception();
207 }
208 exceptional(exceptional&& e) {
209 throw std::exception();
210 }
211 };
212
213 TEST(StaticPtr, Exceptional) {
214 static_ptr<exceptional> p1(std::in_place_type_t<exceptional>{});
215 EXPECT_ANY_THROW(static_ptr<exceptional> p2(std::move(p1)));
216 }