1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/raw_ptr.h"
9
10 #include <cstdint>
11
12 #include <gtest/gtest.h>
13 #include "absl/base/optimization.h"
14
15 namespace google {
16 namespace protobuf {
17 namespace internal {
18 namespace {
19
TEST(ZeroCacheline,Basic)20 TEST(ZeroCacheline, Basic) {
21 for (int i = 0; i < ABSL_CACHELINE_SIZE; ++i) {
22 EXPECT_EQ(kZeroBuffer[i], 0) << i;
23 }
24 EXPECT_EQ(reinterpret_cast<uintptr_t>(kZeroBuffer) % ABSL_CACHELINE_SIZE, 0);
25 }
26
27 struct Obj {
28 int i;
29 };
30
TEST(RawPtr,Basic)31 TEST(RawPtr, Basic) {
32 RawPtr<Obj> raw;
33 EXPECT_EQ(raw->i, 0);
34 EXPECT_EQ((*raw).i, 0);
35 EXPECT_EQ(static_cast<void*>(&raw->i), kZeroBuffer);
36 EXPECT_EQ(static_cast<void*>(raw.Get()), kZeroBuffer);
37 EXPECT_TRUE(raw.IsDefault());
38
39 Obj obj = {1};
40 raw.Set(&obj);
41 EXPECT_EQ(raw->i, 1);
42 EXPECT_EQ(static_cast<void*>(raw.Get()), &obj);
43 EXPECT_FALSE(raw.IsDefault());
44 }
45
TEST(RawPtr,Constexpr)46 TEST(RawPtr, Constexpr) {
47 constexpr RawPtr<Obj> raw;
48 EXPECT_EQ(raw->i, 0);
49 EXPECT_EQ((*raw).i, 0);
50 EXPECT_EQ(static_cast<void*>(&raw->i), kZeroBuffer);
51 EXPECT_EQ(static_cast<void*>(raw.Get()), kZeroBuffer);
52 EXPECT_TRUE(raw.IsDefault());
53
54 static constexpr Obj obj = {1};
55 constexpr RawPtr<Obj> raw2(&obj);
56 EXPECT_EQ(raw2->i, 1);
57 EXPECT_EQ((*raw2).i, 1);
58 EXPECT_EQ(static_cast<void*>(raw2.Get()), &obj);
59 EXPECT_FALSE(raw2.IsDefault());
60 }
61
TEST(RawPtr,DeleteIfNotDefault)62 TEST(RawPtr, DeleteIfNotDefault) {
63 RawPtr<Obj> raw;
64 EXPECT_TRUE(raw.IsDefault());
65
66 // Shouldn't trigger an allocator problem by deallocating default ptr.
67 raw.DeleteIfNotDefault();
68
69 raw.Set(new Obj());
70 EXPECT_FALSE(raw.IsDefault());
71
72 // Shouldn't leak.
73 raw.DeleteIfNotDefault();
74 }
75
TEST(RawPtr,ClearIfNotDefault)76 TEST(RawPtr, ClearIfNotDefault) {
77 struct ObjectWithClear {
78 int called = 0;
79 void Clear() { ++called; }
80 };
81 RawPtr<ObjectWithClear> raw;
82 EXPECT_TRUE(raw.IsDefault());
83
84 // Shouldn't trigger / crash
85 raw.ClearIfNotDefault();
86 EXPECT_EQ(raw.Get()->called, 0);
87
88 raw.Set(new ObjectWithClear());
89 EXPECT_FALSE(raw.IsDefault());
90
91 // Should invoke Clear
92 raw.ClearIfNotDefault();
93 EXPECT_EQ(raw.Get()->called, 1);
94
95 raw.DeleteIfNotDefault();
96 }
97
98 } // namespace
99 } // namespace internal
100 } // namespace protobuf
101 } // namespace google
102