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