ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ResultTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ResultTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/unit_test.hpp>
10 
11 #include <iostream>
12 #include <string>
13 #include <system_error>
14 
16 
17 using namespace std::string_literals;
18 
19 namespace {
20 enum class MyError { Failure = 1, SomethingElse = 2 };
21 
22 std::error_code make_error_code(MyError e) {
23  return {static_cast<int>(e), std::generic_category()};
24 }
25 } // namespace
26 
27 namespace std {
28 // register with STL
29 template <>
30 struct is_error_code_enum<MyError> : std::true_type {};
31 } // namespace std
32 
33 namespace Acts {
34 
35 namespace Test {
36 
37 BOOST_AUTO_TEST_SUITE(Utilities)
38 
39 BOOST_AUTO_TEST_CASE(TestConstruction) {
40  {
41  using Result = Result<int, char>;
42 
43  Result res = Result::success(42);
44  BOOST_CHECK_EQUAL(*res, 42);
45  BOOST_CHECK_EQUAL(res.value(), 42);
46  BOOST_CHECK(res.ok());
47  res = Result::success('e');
48  BOOST_CHECK_EQUAL(*res, 'e');
49  BOOST_CHECK_EQUAL(res.value(), 'e');
50  BOOST_CHECK(res.ok());
51  res = Result::failure(42);
52  BOOST_CHECK(!res.ok());
53  BOOST_CHECK_EQUAL(res.error(), 42);
54  BOOST_CHECK_THROW(res.value(), std::runtime_error);
55  res = Result::failure('e');
56  BOOST_CHECK(!res.ok());
57  BOOST_CHECK_EQUAL(res.error(), 'e');
58  BOOST_CHECK_THROW(res.value(), std::runtime_error);
59  }
60 
61  {
63 
64  Result res1("hallo");
65  BOOST_CHECK(!res1.ok());
66  BOOST_CHECK_EQUAL(res1.error(), "hallo");
67  BOOST_CHECK_THROW(res1.value(), std::runtime_error);
68  res1 = Result::failure("hallo");
69  BOOST_CHECK(!res1.ok());
70  BOOST_CHECK_EQUAL(res1.error(), "hallo");
71  BOOST_CHECK_THROW(res1.value(), std::runtime_error);
72 
73  Result res2(4.5);
74  BOOST_CHECK(res2.ok());
75  BOOST_CHECK(*res2 == 4.5);
76  BOOST_CHECK(res2.value() == 4.5);
77  res2 = Result::success(4.5);
78  BOOST_CHECK(res2.ok());
79  BOOST_CHECK_EQUAL(*res2, 4.5);
80  BOOST_CHECK_EQUAL(res2.value(), 4.5);
81  }
82 }
83 
84 BOOST_AUTO_TEST_CASE(TestErrorCodes) {
85  auto err1 = MyError::Failure;
86 
87  std::error_code ec = err1;
88 
89  {
91 
92  Result res(42);
93  BOOST_CHECK(res.ok());
94  BOOST_CHECK_EQUAL(*res, 42.);
95 
96  Result res2(err1);
97  BOOST_CHECK(!res2.ok());
98  BOOST_CHECK_EQUAL(res2.error(), err1);
99  BOOST_CHECK_THROW(res2.value(), std::runtime_error);
100  }
101 
102  {
104 
105  Result res(42);
106  BOOST_CHECK(res.ok());
107  BOOST_CHECK_EQUAL(*res, 42.);
108  BOOST_CHECK_EQUAL(res.value(), 42u);
109  res = 46;
110  BOOST_CHECK(res.ok());
111  BOOST_CHECK_EQUAL(*res, 46.);
112  BOOST_CHECK_EQUAL(res.value(), 46u);
113 
114  Result res2(ec);
115  BOOST_CHECK(!res2.ok());
116  BOOST_CHECK_EQUAL(res2.error(), ec);
117  BOOST_CHECK_EQUAL(res2.error(), err1);
118 
119  res2 = MyError::SomethingElse;
120  BOOST_CHECK(!res2.ok());
121  BOOST_CHECK_EQUAL(res2.error(), MyError::SomethingElse);
122  BOOST_CHECK(res2.error() != MyError::Failure);
123  }
124 
125  {
127  Result res{0};
128  BOOST_CHECK(res.ok());
129  BOOST_CHECK_EQUAL(*res, 0.0);
130 
131  res = 1;
132  BOOST_CHECK(res.ok());
133  BOOST_CHECK_EQUAL(*res, 1.0);
134 
135  Result res2{"blubb"};
136  BOOST_CHECK(!res2.ok());
137  BOOST_CHECK_EQUAL(res2.error(), "blubb");
138  res2 = "sep";
139  BOOST_CHECK(!res2.ok());
140  BOOST_CHECK_EQUAL(res2.error(), "sep");
141  }
142 
143  {
145  Result res{0};
146  BOOST_CHECK(!res.ok());
147  BOOST_CHECK_EQUAL(res.error(), 0.0);
148 
149  res = "blibb";
150  BOOST_CHECK(res.ok());
151  BOOST_CHECK_EQUAL(res.value(), "blibb");
152 
153  Result res2{"blibb"};
154  BOOST_CHECK(res2.ok());
155  BOOST_CHECK_EQUAL(res2.value(), "blibb");
156 
157  res2 = 0;
158  BOOST_CHECK(!res2.ok());
159  BOOST_CHECK_EQUAL(res2.error(), 0.0);
160  }
161 
162  {
163  using Result = Result<double, int>;
164  Result res = Result::success(2);
165  BOOST_CHECK(res.ok());
166  BOOST_CHECK_EQUAL(res.value(), 2.0);
167 
168  res = Result::failure(3);
169  BOOST_CHECK(!res.ok());
170  BOOST_CHECK_EQUAL(res.error(), 3);
171 
172  Result res2 = Result::failure(2);
173  BOOST_CHECK(!res2.ok());
174  BOOST_CHECK_EQUAL(res2.error(), 2);
175 
176  res2 = Result::success(3.3);
177  BOOST_CHECK(res2.ok());
178  BOOST_CHECK_EQUAL(res2.value(), 3.3);
179  }
180 
181  {
182  using Result = Result<double>;
183 
184  Result res(42);
185  BOOST_CHECK(res.ok());
186  BOOST_CHECK_EQUAL(*res, 42.);
187  BOOST_CHECK_EQUAL(res.value(), 42u);
188  res = 46;
189  BOOST_CHECK(res.ok());
190  BOOST_CHECK_EQUAL(*res, 46.);
191  BOOST_CHECK_EQUAL(res.value(), 46u);
192 
193  Result res2(ec);
194  BOOST_CHECK(!res2.ok());
195  BOOST_CHECK_EQUAL(res2.error(), ec);
196  BOOST_CHECK_EQUAL(res2.error(), err1);
197 
198  res2 = MyError::SomethingElse;
199  BOOST_CHECK(!res2.ok());
200  BOOST_CHECK_EQUAL(res2.error(), MyError::SomethingElse);
201  BOOST_CHECK(res2.error() != MyError::Failure);
202  }
203 
204  {
205  using Result = Result<std::string>;
206 
207  Result res("hallo");
208 
209  BOOST_CHECK(res.ok());
210  BOOST_CHECK_EQUAL(*res, "hallo");
211  BOOST_CHECK_EQUAL(res.value(), "hallo");
212 
213  res = "something else";
214  BOOST_CHECK(res.ok());
215  BOOST_CHECK_EQUAL(*res, "something else");
216  BOOST_CHECK_EQUAL(res.value(), "something else");
217 
218  res = MyError::SomethingElse;
219  BOOST_CHECK(!res.ok());
220  BOOST_CHECK_EQUAL(res.error(), MyError::SomethingElse);
221  BOOST_CHECK(res.error() != MyError::Failure);
222  }
223 
224  {
226 
227  Result res{"hallo"};
228  BOOST_CHECK(res.ok());
229  BOOST_CHECK_EQUAL(res.value(), "hallo");
230 
231  Result res2{4};
232  BOOST_CHECK(!res2.ok());
233  BOOST_CHECK_EQUAL(res2.error(), 4);
234  }
235 }
236 
237 struct NoCopy {
238  NoCopy(int i) : num(i){};
239  NoCopy(const NoCopy&) = delete;
240  NoCopy& operator=(const NoCopy&) = delete;
241  NoCopy(NoCopy&&) = default;
242  NoCopy& operator=(NoCopy&&) = default;
243 
244  int num;
245 };
246 
247 Result<NoCopy> make_nocopy(int i, bool v = true) {
248  if (!v) {
249  return MyError::Failure;
250  }
251  return i;
252 }
253 
254 BOOST_AUTO_TEST_CASE(CopyBehaviour) {
255  using Result = Result<NoCopy>;
256 
257  NoCopy n(5);
258  Result res = std::move(n);
259  BOOST_CHECK(res.ok());
260  BOOST_CHECK_EQUAL((*res).num, res.value().num);
261 
262  res = make_nocopy(3);
263  BOOST_CHECK(res.ok());
264  BOOST_CHECK_EQUAL((*res).num, res.value().num);
265  BOOST_CHECK_EQUAL((*res).num, 3);
266 
267  res = NoCopy(-4);
268  BOOST_CHECK(res.ok());
269  BOOST_CHECK_EQUAL((*res).num, res.value().num);
270  BOOST_CHECK_EQUAL((*res).num, -4.);
271 
272  NoCopy n2 = make_nocopy(7).value();
273  BOOST_CHECK_EQUAL(n2.num, 7);
274  BOOST_REQUIRE_THROW(make_nocopy(6, false).value();, std::runtime_error);
275 
276  Result n4r = make_nocopy(8);
277  BOOST_CHECK(n4r.ok());
278  BOOST_CHECK_EQUAL((*n4r).num, 8);
279  NoCopy n4 = std::move(n4r.value());
280  BOOST_CHECK_EQUAL(n4.num, 8);
281 }
282 
284  (void)b;
285  if (b > 5) {
286  return MyError::SomethingElse;
287  }
288  return {};
289 }
290 
291 BOOST_AUTO_TEST_CASE(VoidResult) {
292  using Result = Result<void>;
293 
294  Result res;
295  BOOST_CHECK(res.ok());
296 
297  Result res2 = Result::success();
298  BOOST_CHECK(res2.ok());
299 
300  res = MyError::Failure;
301  BOOST_CHECK(!res.ok());
302  BOOST_CHECK_EQUAL(res.error(), MyError::Failure);
303 
304  Result res3 = Result::failure(MyError::SomethingElse);
305  BOOST_CHECK(!res3.ok());
306  BOOST_CHECK_EQUAL(res3.error(), MyError::SomethingElse);
307 
308  Result res4 = void_res_func(4);
309  BOOST_CHECK(res4.ok());
310 
311  Result res5 = void_res_func(42);
312  BOOST_CHECK(!res5.ok());
313  BOOST_CHECK_EQUAL(res5.error(), MyError::SomethingElse);
314 }
315 
316 BOOST_AUTO_TEST_CASE(BoolResult) {
317  using Result = Result<bool>;
318 
319  Result res = Result::success(false);
320  BOOST_CHECK(res.ok());
321  BOOST_CHECK_EQUAL(*res, false);
322 
323  res = Result::success(true);
324  BOOST_CHECK(res.ok());
325  BOOST_CHECK_EQUAL(*res, true);
326 
327  res = Result::failure(MyError::Failure);
328  BOOST_CHECK(!res.ok());
329  BOOST_CHECK_EQUAL(res.error(), MyError::Failure);
330 }
331 
332 BOOST_AUTO_TEST_SUITE_END()
333 } // namespace Test
334 } // namespace Acts