Add a test for ref and owned in std::vector.
[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 #include <vector>
17
18 #include "zcpointer.h"
19
20 class C {
21 public:
22 ~C() {}
23
24 void DoThing() {}
25 };
26
27 #define EXPECT(expr) do { if (!(expr)) { throw std::logic_error(#expr); } } while(0)
28
29 #define EXPECT_UAF(expr) do { \
30 try { \
31 (expr); \
32 throw std::logic_error("Expected use-after-free: " #expr); \
33 } catch (zc::UseAfterFreeError) {} \
34 } while(0)
35
36 void TestReset() {
37 zc::owned<C> c(new C());
38 zc::ref<C> owned = c.get();
39 zc::ref<C> owned2 = owned;
40 c.reset();
41 EXPECT_UAF(owned2->DoThing());
42 }
43
44 template <typename T>
45 void TestUnwrap() {
46 zc::owned<T> t(new T());
47 //T* unwrap = t.get();
48
49 zc::ref<T> ref = t.get();
50 T* unwrap2 = ref;
51 }
52
53 void TestMove() {
54 zc::owned<C> c(new C());
55 zc::ref<C> owned = c.get();
56
57 zc::owned<C> c2(std::move(c));
58 owned->DoThing();
59
60 c2.reset();
61 EXPECT_UAF(owned->DoThing());
62 }
63
64 void PtrHelper(zc::ref<C>* out) {
65 zc::owned<C> c(new C());
66 *out = c.get();
67 }
68
69 void TestPtr() {
70 zc::ref<C> ref;
71 PtrHelper(&ref);
72 EXPECT_UAF(ref->DoThing());
73 }
74
75 void TestEquality() {
76 zc::owned<C> a(new C());
77 zc::owned<C> b(new C());
78
79 EXPECT(a == a);
80 EXPECT(b == b);
81 EXPECT(a != b);
82
83 zc::ref<C> ra = a.get();
84 zc::ref<C> rb = b.get();
85
86 EXPECT(ra == ra);
87 EXPECT(ra == a.get());
88 EXPECT(rb == rb);
89 EXPECT(rb == b.get());
90
91 EXPECT(rb != ra);
92
93 zc::ref<C> r = a.get();
94 EXPECT(r == ra);
95 EXPECT(r == a.get());
96
97 zc::owned<C> c;
98 zc::owned<C> c2;
99 zc::ref<C> rc = nullptr;
100
101 EXPECT(rc == c.get());
102 EXPECT(c == nullptr);
103 EXPECT(rc == nullptr);
104 EXPECT(a != c);
105 EXPECT(c == c2);
106 }
107
108 void TestNulls() {
109 zc::owned<C> l;
110 zc::owned<C> r;
111
112 zc::ref<C> rl = l.get();
113 zc::ref<C> rr = r.get();
114
115 r = std::move(l);
116 rl = rr;
117
118 EXPECT(l == nullptr);
119 EXPECT(r == nullptr);
120 EXPECT(rl == nullptr);
121 EXPECT(rr == nullptr);
122 }
123
124 void TestVector() {
125 zc::owned<C> c;
126 std::vector<zc::ref<C>> vec{
127 c.get(),
128 c.get(),
129 c.get()
130 };
131
132 for (const auto& r : vec) {
133 EXPECT(r == c.get());
134 }
135
136 zc::ref<C> ref;
137 {
138 std::vector<zc::owned<C>> vec;
139 vec.push_back(std::move(zc::owned<C>(new C())));
140 vec.push_back(std::move(zc::owned<C>(new C())));
141 vec.push_back(std::move(zc::owned<C>(new C())));
142 ref = vec[1].get();
143 }
144 EXPECT_UAF(ref->DoThing());
145 }
146
147 #define TEST_FUNC(fn) { #fn , Test##fn }
148
149 int main() {
150 struct {
151 const char* name;
152 void (*test)();
153 } kTests[] = {
154 TEST_FUNC(Reset),
155 TEST_FUNC(Move),
156 TEST_FUNC(Ptr),
157 TEST_FUNC(Equality),
158 TEST_FUNC(Nulls),
159 TEST_FUNC(Vector),
160 };
161
162 bool passed = true;
163 for (const auto& test : kTests) {
164 std::cout << "=== BEGIN " << test.name << " ===" << std::endl;
165 try {
166 test.test();
167 std::cout << "=== PASS " << test.name << " ===" << std::endl;
168 } catch (const std::logic_error& e) {
169 passed = false;
170 std::cout << "=== FAIL " << test.name
171 << ": Assertion failure: " << e.what() << " ===" << std::endl;
172 }
173 }
174
175 return passed ? 0 : 1;
176 }