ref<T>::ref() now initializes to nullptr. Improve boolean comparisons for ref.
[zcpointer.git] / test.cc
1 // Copyright 2016 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <iostream>
16
17 #include "zcpointer.h"
18
19 class C {
20 public:
21 ~C() {}
22
23 void DoThing() {}
24 };
25
26 #define EXPECT(expr) do { if (!(expr)) { throw std::logic_error(#expr); } } while(0)
27
28 #define EXPECT_UAF(expr) do { \
29 try { \
30 (expr); \
31 throw std::logic_error("Expected use-after-free: " #expr); \
32 } catch (zc::UseAfterFreeError) {} \
33 } while(0)
34
35 void TestReset() {
36 zc::owned<C> c(new C());
37 zc::ref<C> owned = c.get();
38 zc::ref<C> owned2 = owned;
39 c.reset();
40 EXPECT_UAF(owned2->DoThing());
41 }
42
43 template <typename T>
44 void TestUnwrap() {
45 zc::owned<T> t(new T());
46 //T* unwrap = t.get();
47
48 zc::ref<T> ref = t.get();
49 T* unwrap2 = ref;
50 }
51
52 void TestMove() {
53 zc::owned<C> c(new C());
54 zc::ref<C> owned = c.get();
55
56 zc::owned<C> c2(std::move(c));
57 owned->DoThing();
58
59 c2.reset();
60 EXPECT_UAF(owned->DoThing());
61 }
62
63 void PtrHelper(zc::ref<C>* out) {
64 zc::owned<C> c(new C());
65 *out = c.get();
66 }
67
68 void TestPtr() {
69 zc::ref<C> ref;
70 PtrHelper(&ref);
71 EXPECT_UAF(ref->DoThing());
72 }
73
74 void TestEquality() {
75 zc::owned<C> a(new C());
76 zc::owned<C> b(new C());
77
78 EXPECT(a == a);
79 EXPECT(b == b);
80 EXPECT(a != b);
81
82 zc::ref<C> ra = a.get();
83 zc::ref<C> rb = b.get();
84
85 EXPECT(ra == ra);
86 EXPECT(ra == a.get());
87 EXPECT(rb == rb);
88 EXPECT(rb == b.get());
89
90 EXPECT(rb != ra);
91
92 zc::ref<C> r = a.get();
93 EXPECT(r == ra);
94 EXPECT(r == a.get());
95
96 zc::owned<C> c;
97 zc::owned<C> c2;
98 zc::ref<C> rc = nullptr;
99
100 EXPECT(rc == c.get());
101 EXPECT(c == nullptr);
102 EXPECT(rc == nullptr);
103 EXPECT(a != c);
104 EXPECT(c == c2);
105 }
106
107 void TestNulls() {
108 zc::owned<C> l;
109 zc::owned<C> r;
110
111 zc::ref<C> rl = l.get();
112 zc::ref<C> rr = r.get();
113
114 r = std::move(l);
115 rl = rr;
116
117 EXPECT(l == nullptr);
118 EXPECT(r == nullptr);
119 EXPECT(rl == nullptr);
120 EXPECT(rr == nullptr);
121 }
122
123 #define TEST_FUNC(fn) { #fn , Test##fn }
124
125 int main() {
126 struct {
127 const char* name;
128 void (*test)();
129 } kTests[] = {
130 TEST_FUNC(Reset),
131 TEST_FUNC(Move),
132 TEST_FUNC(Ptr),
133 TEST_FUNC(Equality),
134 TEST_FUNC(Nulls),
135 };
136
137 bool passed = true;
138 for (const auto& test : kTests) {
139 std::cout << "=== BEGIN " << test.name << " ===" << std::endl;
140 try {
141 test.test();
142 std::cout << "=== PASS " << test.name << " ===" << std::endl;
143 } catch (const std::logic_error& e) {
144 passed = false;
145 std::cout << "=== FAIL " << test.name
146 << ": Assertion failure: " << e.what() << " ===" << std::endl;
147 }
148 }
149
150 return passed ? 0 : 1;
151 }