blob: 5f4daed521c04c181038a69d93011780f2311b51 [file] [log] [blame]
Mårten Kongstad1e99b172019-01-28 08:49:12 +01001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <memory>
18#include <type_traits>
19#include <utility>
20
21#include "gmock/gmock.h"
22#include "gtest/gtest.h"
23
24#include "idmap2/Result.h"
25
26namespace android::idmap2 {
27
28struct Container {
29 uint32_t value; // NOLINT(misc-non-private-member-variables-in-classes)
30};
31
32// Tests: Error
33
34TEST(ResultTests, ErrorTraits) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +010035 ASSERT_TRUE(std::is_move_constructible<Error>::value);
36 ASSERT_TRUE(std::is_move_assignable<Error>::value);
37 ASSERT_TRUE(std::is_copy_constructible<Error>::value);
38 ASSERT_TRUE(std::is_copy_assignable<Error>::value);
Mårten Kongstad1e99b172019-01-28 08:49:12 +010039}
40
41TEST(ResultTests, ErrorCtorFormat) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +010042 Error e("%s=0x%08x", "resid", 0x7f010002);
Mårten Kongstad1e99b172019-01-28 08:49:12 +010043 ASSERT_EQ(e.GetMessage(), "resid=0x7f010002");
44}
45
46TEST(ResultTests, ErrorPropagateParent) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +010047 Error e1("foo");
Mårten Kongstad1e99b172019-01-28 08:49:12 +010048 ASSERT_EQ(e1.GetMessage(), "foo");
49
Mårten Kongstad49d835d2019-01-31 10:50:48 +010050 Error e2(e1, "bar");
Mårten Kongstad1e99b172019-01-28 08:49:12 +010051 ASSERT_EQ(e2.GetMessage(), "foo -> bar");
52
Mårten Kongstad49d835d2019-01-31 10:50:48 +010053 Error e3(e2); // NOLINT(performance-unnecessary-copy-initialization)
Mårten Kongstad1e99b172019-01-28 08:49:12 +010054 ASSERT_EQ(e3.GetMessage(), "foo -> bar");
55
Mårten Kongstad49d835d2019-01-31 10:50:48 +010056 Error e4(e3, "%02d", 1);
Mårten Kongstad1e99b172019-01-28 08:49:12 +010057 ASSERT_EQ(e4.GetMessage(), "foo -> bar -> 01");
58}
59
60// Tests: Result<T> member functions
61
62// Result(const Result&)
63TEST(ResultTests, CopyConstructor) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +010064 Result<uint32_t> r1(42U);
Mårten Kongstad1e99b172019-01-28 08:49:12 +010065
Mårten Kongstad49d835d2019-01-31 10:50:48 +010066 Result<uint32_t> r2(r1);
Mårten Kongstad1e99b172019-01-28 08:49:12 +010067 ASSERT_TRUE(r2);
68 ASSERT_EQ(*r2, 42U);
69
Mårten Kongstad49d835d2019-01-31 10:50:48 +010070 Result<uint32_t> r3 = r2;
Mårten Kongstad1e99b172019-01-28 08:49:12 +010071 ASSERT_TRUE(r3);
72 ASSERT_EQ(*r3, 42U);
73}
74
75// Result(const T&)
76TEST(ResultTests, Constructor) {
77 uint32_t v = 42U;
Mårten Kongstad49d835d2019-01-31 10:50:48 +010078 Result<uint32_t> r1(v);
Mårten Kongstad1e99b172019-01-28 08:49:12 +010079 ASSERT_TRUE(r1);
80 ASSERT_EQ(*r1, 42U);
81
Mårten Kongstad49d835d2019-01-31 10:50:48 +010082 Error e("foo");
83 Result<uint32_t> r2(e);
Mårten Kongstad1e99b172019-01-28 08:49:12 +010084 ASSERT_FALSE(r2);
85 ASSERT_EQ(r2.GetErrorMessage(), "foo");
86}
87
88// Result(const T&&)
89TEST(ResultTests, MoveConstructor) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +010090 Result<uint32_t> r1(42U);
Mårten Kongstad1e99b172019-01-28 08:49:12 +010091 ASSERT_TRUE(r1);
92 ASSERT_EQ(*r1, 42U);
93
Mårten Kongstad49d835d2019-01-31 10:50:48 +010094 Result<uint32_t> r2(Error("foo"));
Mårten Kongstad1e99b172019-01-28 08:49:12 +010095 ASSERT_FALSE(r2);
96 ASSERT_EQ(r2.GetErrorMessage(), "foo");
97}
98
99// operator=
100TEST(ResultTests, CopyAssignmentOperator) {
101 // note: 'Result<...> r2 = r1;' calls the copy ctor
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100102 Result<uint32_t> r1(42U);
103 Result<uint32_t> r2(0U);
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100104 r2 = r1;
105 ASSERT_TRUE(r2);
106 ASSERT_EQ(*r2, 42U);
107
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100108 Result<uint32_t> r3(Error("foo"));
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100109 r2 = r3;
110 ASSERT_FALSE(r2);
111 ASSERT_EQ(r2.GetErrorMessage(), "foo");
112}
113
114TEST(ResultTests, MoveAssignmentOperator) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100115 Result<uint32_t> r(0U);
116 r = Result<uint32_t>(42U);
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100117 ASSERT_TRUE(r);
118 ASSERT_EQ(*r, 42U);
119
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100120 r = Result<uint32_t>(Error("foo"));
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100121 ASSERT_FALSE(r);
122 ASSERT_EQ(r.GetErrorMessage(), "foo");
123}
124
125// operator bool()
126TEST(ResultTests, BoolOperator) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100127 Result<uint32_t> r1(42U);
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100128 ASSERT_TRUE(r1);
129 ASSERT_EQ(*r1, 42U);
130
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100131 Result<uint32_t> r2(Error("foo"));
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100132 ASSERT_FALSE(r2);
133 ASSERT_EQ(r2.GetErrorMessage(), "foo");
134}
135
136// operator*
137TEST(ResultTests, IndirectionOperator) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100138 const Result<uint32_t> r1(42U);
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100139 ASSERT_TRUE(r1);
140 ASSERT_EQ(*r1, 42U);
141
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100142 const Result<Container> r2(Container{42U});
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100143 ASSERT_TRUE(r2);
144 const Container& c = *r2;
145 ASSERT_EQ(c.value, 42U);
146
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100147 Result<Container> r3(Container{42U});
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100148 ASSERT_TRUE(r3);
149 ASSERT_EQ((*r3).value, 42U);
150 (*r3).value = 0U;
151 ASSERT_EQ((*r3).value, 0U);
152}
153
154// operator->
155TEST(ResultTests, DereferenceOperator) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100156 const Result<Container> r1(Container{42U});
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100157 ASSERT_TRUE(r1);
158 ASSERT_EQ(r1->value, 42U);
159
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100160 Result<Container> r2(Container{42U});
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100161 ASSERT_TRUE(r2);
162 ASSERT_EQ(r2->value, 42U);
163 r2->value = 0U;
164 ASSERT_EQ(r2->value, 0U);
165}
166
167// Tests: intended use of Result<T>
168
169TEST(ResultTests, ResultTraits) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100170 ASSERT_TRUE(std::is_move_constructible<Result<uint32_t>>::value);
171 ASSERT_TRUE(std::is_move_assignable<Result<uint32_t>>::value);
172 ASSERT_TRUE(std::is_copy_constructible<Result<uint32_t>>::value);
173 ASSERT_TRUE(std::is_copy_assignable<Result<uint32_t>>::value);
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100174}
175
176TEST(ResultTests, UnitTypeResult) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100177 Result<Unit> r(Unit{});
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100178 ASSERT_TRUE(r);
179}
180
181struct RefCountData {
182 int ctor; // NOLINT(misc-non-private-member-variables-in-classes)
183 int copy_ctor; // NOLINT(misc-non-private-member-variables-in-classes)
184 int dtor; // NOLINT(misc-non-private-member-variables-in-classes)
185 int move; // NOLINT(misc-non-private-member-variables-in-classes)
186};
187
188class RefCountContainer {
189 public:
190 explicit RefCountContainer(RefCountData& data) : data_(data) {
191 ++data_.ctor;
192 }
193
194 RefCountContainer(RefCountContainer const&) = delete;
195
196 RefCountContainer(RefCountContainer&& rhs) noexcept : data_(rhs.data_) {
197 ++data_.copy_ctor;
198 }
199
200 RefCountContainer& operator=(RefCountContainer const&) = delete;
201
202 RefCountContainer& operator=(RefCountContainer&& rhs) noexcept {
203 data_ = rhs.data_;
204 ++data_.move;
205 return *this;
206 }
207
208 ~RefCountContainer() {
209 ++data_.dtor;
210 }
211
212 private:
213 RefCountData& data_;
214};
215
216TEST(ResultTests, ReferenceCount) {
217 ASSERT_TRUE(std::is_move_constructible<RefCountContainer>::value);
218 ASSERT_TRUE(std::is_move_assignable<RefCountContainer>::value);
219 ASSERT_FALSE(std::is_copy_constructible<RefCountContainer>::value);
220 ASSERT_FALSE(std::is_copy_assignable<RefCountContainer>::value);
221
222 RefCountData rc{0, 0, 0, 0};
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100223 { Result<RefCountContainer> r(RefCountContainer{rc}); }
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100224 ASSERT_EQ(rc.ctor, 1);
225 ASSERT_EQ(rc.copy_ctor, 1);
226 ASSERT_EQ(rc.move, 0);
227 ASSERT_EQ(rc.dtor, 2);
228}
229
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100230Result<Container> CreateContainer(bool succeed) {
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100231 if (!succeed) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100232 return Error("foo");
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100233 }
234 return Container{42U};
235}
236
237TEST(ResultTests, FunctionReturn) {
238 auto r1 = CreateContainer(true);
239 ASSERT_TRUE(r1);
240 ASSERT_EQ(r1->value, 42U);
241
242 auto r2 = CreateContainer(false);
243 ASSERT_FALSE(r2);
244 ASSERT_EQ(r2.GetErrorMessage(), "foo");
245 ASSERT_EQ(r2.GetError().GetMessage(), "foo");
246}
247
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100248Result<Container> FailToCreateContainer() {
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100249 auto container = CreateContainer(false);
250 if (!container) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100251 return Error(container.GetError(), "bar");
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100252 }
253 return container;
254}
255
256TEST(ResultTests, CascadeError) {
257 auto container = FailToCreateContainer();
258 ASSERT_FALSE(container);
259 ASSERT_EQ(container.GetErrorMessage(), "foo -> bar");
260}
261
262struct NoCopyContainer {
263 uint32_t value; // NOLINT(misc-non-private-member-variables-in-classes)
264 DISALLOW_COPY_AND_ASSIGN(NoCopyContainer);
265};
266
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100267Result<std::unique_ptr<NoCopyContainer>> CreateNoCopyContainer(bool succeed) {
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100268 if (!succeed) {
Mårten Kongstad49d835d2019-01-31 10:50:48 +0100269 return Error("foo");
Mårten Kongstad1e99b172019-01-28 08:49:12 +0100270 }
271 std::unique_ptr<NoCopyContainer> p(new NoCopyContainer{0U});
272 p->value = 42U;
273 return std::move(p);
274}
275
276TEST(ResultTests, UniquePtr) {
277 auto r1 = CreateNoCopyContainer(true);
278 ASSERT_TRUE(r1);
279 ASSERT_EQ((*r1)->value, 42U);
280 (*r1)->value = 0U;
281 ASSERT_EQ((*r1)->value, 0U);
282
283 auto r2 = CreateNoCopyContainer(false);
284 ASSERT_FALSE(r2);
285 ASSERT_EQ(r2.GetErrorMessage(), "foo");
286}
287
288} // namespace android::idmap2