1f7f6d3e9SLang Hames //===----- unittests/ErrorTest.cpp - Error.h tests ------------------------===//
2f7f6d3e9SLang Hames //
3f7f6d3e9SLang Hames //                     The LLVM Compiler Infrastructure
4f7f6d3e9SLang Hames //
5f7f6d3e9SLang Hames // This file is distributed under the University of Illinois Open Source
6f7f6d3e9SLang Hames // License. See LICENSE.TXT for details.
7f7f6d3e9SLang Hames //
8f7f6d3e9SLang Hames //===----------------------------------------------------------------------===//
9f7f6d3e9SLang Hames 
10f7f6d3e9SLang Hames #include "llvm/Support/Error.h"
11f7f6d3e9SLang Hames #include "llvm/Support/Errc.h"
12f7f6d3e9SLang Hames #include "gtest/gtest.h"
13f7f6d3e9SLang Hames #include <memory>
14f7f6d3e9SLang Hames 
15f7f6d3e9SLang Hames using namespace llvm;
16f7f6d3e9SLang Hames 
17f7f6d3e9SLang Hames namespace {
18f7f6d3e9SLang Hames 
19f7f6d3e9SLang Hames // Test:
20f7f6d3e9SLang Hames //
21f7f6d3e9SLang Hames // Constructing success.
22f7f6d3e9SLang Hames //   - Silent acceptance of tested success.
23f7f6d3e9SLang Hames //   - Programmatic error on untested success.
24f7f6d3e9SLang Hames //
25f7f6d3e9SLang Hames // Custom error class.
26f7f6d3e9SLang Hames //   - Creation of a custom error class with a default base class.
27f7f6d3e9SLang Hames //   - Handling of a custom error class with a default base class.
28f7f6d3e9SLang Hames //   - Handler type deduction.
29f7f6d3e9SLang Hames //   - Failure to handle a custom error class.
30f7f6d3e9SLang Hames //   - Isa testing of a custom error class.
31f7f6d3e9SLang Hames //
32f7f6d3e9SLang Hames //   - Creation of a custom error class with a custom base class.
33f7f6d3e9SLang Hames //   - Handling of a custom error class with a default base class.
34f7f6d3e9SLang Hames //   - Correct shadowing of handlers.
35f7f6d3e9SLang Hames //
36f7f6d3e9SLang Hames // Utility functions:
37f7f6d3e9SLang Hames //   - join_errors to defer errors.
38f7f6d3e9SLang Hames //   - consume_error to consume a "safe" error without any output.
39f7f6d3e9SLang Hames //   - handleAllUnhandledErrors to assert that all errors are handled.
40f7f6d3e9SLang Hames //   - logAllUnhandledErrors to log errors to a stream.
41f7f6d3e9SLang Hames //
42f7f6d3e9SLang Hames // Expected tests:
43f7f6d3e9SLang Hames //   - Expected<T> with T.
44f7f6d3e9SLang Hames //   - Expected<T> with Error.
45f7f6d3e9SLang Hames //   - Failure to handle an Expected<T> in failure mode.
46f7f6d3e9SLang Hames //   - Error extraction (Expected -> Error).
47f7f6d3e9SLang Hames //
48f7f6d3e9SLang Hames // std::error_code:
49f7f6d3e9SLang Hames //   - std::error_code to Error in success mode.
50f7f6d3e9SLang Hames //   - std::error_code to Error (ECError) in failure mode.
51f7f6d3e9SLang Hames //   - Error to std::error_code in success mode.
52f7f6d3e9SLang Hames //   - Error (ECError) to std::error_code in failure mode.
53f7f6d3e9SLang Hames 
54f7f6d3e9SLang Hames // Custom error class with a default base class and some random 'info' attached.
55f7f6d3e9SLang Hames class CustomError : public ErrorInfo<CustomError> {
56f7f6d3e9SLang Hames public:
57f7f6d3e9SLang Hames   // Create an error with some info attached.
58f7f6d3e9SLang Hames   CustomError(int Info) : Info(Info) {}
59f7f6d3e9SLang Hames 
60f7f6d3e9SLang Hames   // Get the info attached to this error.
61f7f6d3e9SLang Hames   int getInfo() const { return Info; }
62f7f6d3e9SLang Hames 
63f7f6d3e9SLang Hames   // Log this error to a stream.
64f7f6d3e9SLang Hames   void log(raw_ostream &OS) const override {
65f7f6d3e9SLang Hames     OS << "CustomError { " << getInfo() << "}";
66f7f6d3e9SLang Hames   }
67f7f6d3e9SLang Hames 
68f7f6d3e9SLang Hames protected:
69f7f6d3e9SLang Hames   // This error is subclassed below, but we can't use inheriting constructors
70f7f6d3e9SLang Hames   // yet, so we can't propagate the constructors through ErrorInfo. Instead
71f7f6d3e9SLang Hames   // we have to have a default constructor and have the subclass initialize all
72f7f6d3e9SLang Hames   // fields.
73f7f6d3e9SLang Hames   CustomError() : Info(0) {}
74f7f6d3e9SLang Hames 
75f7f6d3e9SLang Hames   int Info;
76f7f6d3e9SLang Hames };
77f7f6d3e9SLang Hames 
78f7f6d3e9SLang Hames // Custom error class with a custom base class and some additional random
79f7f6d3e9SLang Hames // 'info'.
80f7f6d3e9SLang Hames class CustomSubError : public ErrorInfo<CustomSubError, CustomError> {
81f7f6d3e9SLang Hames public:
82f7f6d3e9SLang Hames   // Create a sub-error with some info attached.
83f7f6d3e9SLang Hames   CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) {
84f7f6d3e9SLang Hames     this->Info = Info;
85f7f6d3e9SLang Hames   }
86f7f6d3e9SLang Hames 
87f7f6d3e9SLang Hames   // Get the extra info attached to this error.
88f7f6d3e9SLang Hames   int getExtraInfo() const { return ExtraInfo; }
89f7f6d3e9SLang Hames 
90f7f6d3e9SLang Hames   // Log this error to a stream.
91f7f6d3e9SLang Hames   void log(raw_ostream &OS) const override {
92f7f6d3e9SLang Hames     OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}";
93f7f6d3e9SLang Hames   }
94f7f6d3e9SLang Hames 
95f7f6d3e9SLang Hames protected:
96f7f6d3e9SLang Hames   int ExtraInfo;
97f7f6d3e9SLang Hames };
98f7f6d3e9SLang Hames 
99f7f6d3e9SLang Hames // Verify that success values that are checked (i.e. cast to 'bool') are
100f7f6d3e9SLang Hames // destructed without error, and that unchecked success values cause an
101f7f6d3e9SLang Hames // abort.
102f7f6d3e9SLang Hames TEST(Error, CheckSuccess) {
103f7f6d3e9SLang Hames   // Test checked success.
104f7f6d3e9SLang Hames   {
105f7f6d3e9SLang Hames     Error E;
106f7f6d3e9SLang Hames     EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'";
107f7f6d3e9SLang Hames   }
108f7f6d3e9SLang Hames 
109f7f6d3e9SLang Hames // Test unchecked success.
110f7f6d3e9SLang Hames // Test runs in debug mode only.
111f7f6d3e9SLang Hames #ifndef NDEBUG
112f7f6d3e9SLang Hames   {
113f7f6d3e9SLang Hames     auto DropUncheckedSuccess = []() { Error E; };
114f7f6d3e9SLang Hames     EXPECT_DEATH(DropUncheckedSuccess(),
115f7f6d3e9SLang Hames                  "Program aborted due to an unhandled Error:")
116f7f6d3e9SLang Hames         << "Unchecked Error Succes value did not cause abort()";
117f7f6d3e9SLang Hames   }
118f7f6d3e9SLang Hames #endif
119f7f6d3e9SLang Hames }
120f7f6d3e9SLang Hames 
121f7f6d3e9SLang Hames static Error handleCustomError(const CustomError &CE) { return Error(); }
122f7f6d3e9SLang Hames 
123f7f6d3e9SLang Hames static void handleCustomErrorVoid(const CustomError &CE) {}
124f7f6d3e9SLang Hames 
125f7f6d3e9SLang Hames static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) {
126f7f6d3e9SLang Hames   return Error();
127f7f6d3e9SLang Hames }
128f7f6d3e9SLang Hames 
129f7f6d3e9SLang Hames static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {}
130f7f6d3e9SLang Hames 
131f7f6d3e9SLang Hames // Verify creation and handling of custom error classes.
132f7f6d3e9SLang Hames TEST(Error, CheckCustomErrors) {
133f7f6d3e9SLang Hames // Check that we abort on unhandled failure cases. (Force conversion to bool
134f7f6d3e9SLang Hames // to make sure that we don't accidentally treat checked errors as handled).
135f7f6d3e9SLang Hames // Test runs in debug mode only.
136f7f6d3e9SLang Hames #ifndef NDEBUG
137f7f6d3e9SLang Hames   {
138f7f6d3e9SLang Hames     auto DropUnhandledError = []() {
139f7f6d3e9SLang Hames       Error E = make_error<CustomError>(42);
140f7f6d3e9SLang Hames       (void)!E;
141f7f6d3e9SLang Hames     };
142f7f6d3e9SLang Hames     EXPECT_DEATH(DropUnhandledError(),
143f7f6d3e9SLang Hames                  "Program aborted due to an unhandled Error:")
144f7f6d3e9SLang Hames         << "Unhandled Error failure value did not cause abort()";
145f7f6d3e9SLang Hames   }
146f7f6d3e9SLang Hames #endif
147f7f6d3e9SLang Hames 
148f7f6d3e9SLang Hames   // Check 'isA' handling.
149f7f6d3e9SLang Hames   {
150f7f6d3e9SLang Hames     Error E = make_error<CustomError>(1);
151f7f6d3e9SLang Hames     Error F = make_error<CustomSubError>(1, 2);
152*01a3cf4dSLang Hames     Error G = Error::success();
153f7f6d3e9SLang Hames 
154f7f6d3e9SLang Hames     EXPECT_TRUE(E.isA<CustomError>());
155f7f6d3e9SLang Hames     EXPECT_FALSE(E.isA<CustomSubError>());
156f7f6d3e9SLang Hames     EXPECT_TRUE(F.isA<CustomError>());
157f7f6d3e9SLang Hames     EXPECT_TRUE(F.isA<CustomSubError>());
158*01a3cf4dSLang Hames     EXPECT_FALSE(G.isA<CustomError>());
159f7f6d3e9SLang Hames 
160f7f6d3e9SLang Hames     consumeError(std::move(E));
161f7f6d3e9SLang Hames     consumeError(std::move(F));
162*01a3cf4dSLang Hames     consumeError(std::move(G));
163f7f6d3e9SLang Hames   }
164f7f6d3e9SLang Hames 
165f7f6d3e9SLang Hames   // Check that we can handle a custom error.
166f7f6d3e9SLang Hames   {
167f7f6d3e9SLang Hames     int CaughtErrorInfo = 0;
168f7f6d3e9SLang Hames     handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) {
169f7f6d3e9SLang Hames       CaughtErrorInfo = CE.getInfo();
170f7f6d3e9SLang Hames     });
171f7f6d3e9SLang Hames 
172f7f6d3e9SLang Hames     EXPECT_TRUE(CaughtErrorInfo == 42)
173f7f6d3e9SLang Hames         << "Wrong result from CustomError handler";
174f7f6d3e9SLang Hames   }
175f7f6d3e9SLang Hames 
176f7f6d3e9SLang Hames   // Check that handler type deduction also works for handlers
177f7f6d3e9SLang Hames   // of the following types:
178f7f6d3e9SLang Hames   // void (const Err&)
179f7f6d3e9SLang Hames   // Error (const Err&) mutable
180f7f6d3e9SLang Hames   // void (const Err&) mutable
181f7f6d3e9SLang Hames   // Error (Err&)
182f7f6d3e9SLang Hames   // void (Err&)
183f7f6d3e9SLang Hames   // Error (Err&) mutable
184f7f6d3e9SLang Hames   // void (Err&) mutable
185f7f6d3e9SLang Hames   // Error (unique_ptr<Err>)
186f7f6d3e9SLang Hames   // void (unique_ptr<Err>)
187f7f6d3e9SLang Hames   // Error (unique_ptr<Err>) mutable
188f7f6d3e9SLang Hames   // void (unique_ptr<Err>) mutable
189f7f6d3e9SLang Hames 
190f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {});
191f7f6d3e9SLang Hames 
192f7f6d3e9SLang Hames   handleAllErrors(
193f7f6d3e9SLang Hames       make_error<CustomError>(42),
194f7f6d3e9SLang Hames       [](const CustomError &CE) mutable { return Error::success(); });
195f7f6d3e9SLang Hames 
196f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
197f7f6d3e9SLang Hames                   [](const CustomError &CE) mutable {});
198f7f6d3e9SLang Hames 
199f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
200f7f6d3e9SLang Hames                   [](CustomError &CE) { return Error::success(); });
201f7f6d3e9SLang Hames 
202f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {});
203f7f6d3e9SLang Hames 
204f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
205f7f6d3e9SLang Hames                   [](CustomError &CE) mutable { return Error::success(); });
206f7f6d3e9SLang Hames 
207f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {});
208f7f6d3e9SLang Hames 
209f7f6d3e9SLang Hames   handleAllErrors(
210f7f6d3e9SLang Hames       make_error<CustomError>(42),
211f7f6d3e9SLang Hames       [](std::unique_ptr<CustomError> CE) { return Error::success(); });
212f7f6d3e9SLang Hames 
213f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
214f7f6d3e9SLang Hames                   [](std::unique_ptr<CustomError> CE) {});
215f7f6d3e9SLang Hames 
216f7f6d3e9SLang Hames   handleAllErrors(
217f7f6d3e9SLang Hames       make_error<CustomError>(42),
218f7f6d3e9SLang Hames       [](std::unique_ptr<CustomError> CE) mutable { return Error::success(); });
219f7f6d3e9SLang Hames 
220f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
221f7f6d3e9SLang Hames                   [](std::unique_ptr<CustomError> CE) mutable {});
222f7f6d3e9SLang Hames 
223f7f6d3e9SLang Hames   // Check that named handlers of type 'Error (const Err&)' work.
224f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), handleCustomError);
225f7f6d3e9SLang Hames 
226f7f6d3e9SLang Hames   // Check that named handlers of type 'void (const Err&)' work.
227f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid);
228f7f6d3e9SLang Hames 
229f7f6d3e9SLang Hames   // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.
230f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP);
231f7f6d3e9SLang Hames 
232f7f6d3e9SLang Hames   // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.
233f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid);
234f7f6d3e9SLang Hames 
235f7f6d3e9SLang Hames   // Check that we can handle a custom error with a custom base class.
236f7f6d3e9SLang Hames   {
237f7f6d3e9SLang Hames     int CaughtErrorInfo = 0;
238f7f6d3e9SLang Hames     int CaughtErrorExtraInfo = 0;
239f7f6d3e9SLang Hames     handleAllErrors(make_error<CustomSubError>(42, 7),
240f7f6d3e9SLang Hames                     [&](const CustomSubError &SE) {
241f7f6d3e9SLang Hames                       CaughtErrorInfo = SE.getInfo();
242f7f6d3e9SLang Hames                       CaughtErrorExtraInfo = SE.getExtraInfo();
243f7f6d3e9SLang Hames                     });
244f7f6d3e9SLang Hames 
245f7f6d3e9SLang Hames     EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7)
246f7f6d3e9SLang Hames         << "Wrong result from CustomSubError handler";
247f7f6d3e9SLang Hames   }
248f7f6d3e9SLang Hames 
249f7f6d3e9SLang Hames   // Check that we trigger only the first handler that applies.
250f7f6d3e9SLang Hames   {
251f7f6d3e9SLang Hames     int DummyInfo = 0;
252f7f6d3e9SLang Hames     int CaughtErrorInfo = 0;
253f7f6d3e9SLang Hames     int CaughtErrorExtraInfo = 0;
254f7f6d3e9SLang Hames 
255f7f6d3e9SLang Hames     handleAllErrors(make_error<CustomSubError>(42, 7),
256f7f6d3e9SLang Hames                     [&](const CustomSubError &SE) {
257f7f6d3e9SLang Hames                       CaughtErrorInfo = SE.getInfo();
258f7f6d3e9SLang Hames                       CaughtErrorExtraInfo = SE.getExtraInfo();
259f7f6d3e9SLang Hames                     },
260f7f6d3e9SLang Hames                     [&](const CustomError &CE) { DummyInfo = CE.getInfo(); });
261f7f6d3e9SLang Hames 
262f7f6d3e9SLang Hames     EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 &&
263f7f6d3e9SLang Hames                 DummyInfo == 0)
264f7f6d3e9SLang Hames         << "Activated the wrong Error handler(s)";
265f7f6d3e9SLang Hames   }
266f7f6d3e9SLang Hames 
267f7f6d3e9SLang Hames   // Check that general handlers shadow specific ones.
268f7f6d3e9SLang Hames   {
269f7f6d3e9SLang Hames     int CaughtErrorInfo = 0;
270f7f6d3e9SLang Hames     int DummyInfo = 0;
271f7f6d3e9SLang Hames     int DummyExtraInfo = 0;
272f7f6d3e9SLang Hames 
273f7f6d3e9SLang Hames     handleAllErrors(
274f7f6d3e9SLang Hames         make_error<CustomSubError>(42, 7),
275f7f6d3e9SLang Hames         [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); },
276f7f6d3e9SLang Hames         [&](const CustomSubError &SE) {
277f7f6d3e9SLang Hames           DummyInfo = SE.getInfo();
278f7f6d3e9SLang Hames           DummyExtraInfo = SE.getExtraInfo();
279f7f6d3e9SLang Hames         });
280f7f6d3e9SLang Hames 
281f7f6d3e9SLang Hames     EXPECT_TRUE(CaughtErrorInfo = 42 && DummyInfo == 0 && DummyExtraInfo == 0)
282f7f6d3e9SLang Hames         << "General Error handler did not shadow specific handler";
283f7f6d3e9SLang Hames   }
284f7f6d3e9SLang Hames }
285f7f6d3e9SLang Hames 
286f7f6d3e9SLang Hames // Test utility functions.
287f7f6d3e9SLang Hames TEST(Error, CheckErrorUtilities) {
288f7f6d3e9SLang Hames 
289f7f6d3e9SLang Hames   // Test joinErrors
290f7f6d3e9SLang Hames   {
291f7f6d3e9SLang Hames     int CustomErrorInfo1 = 0;
292f7f6d3e9SLang Hames     int CustomErrorInfo2 = 0;
293f7f6d3e9SLang Hames     int CustomErrorExtraInfo = 0;
294f7f6d3e9SLang Hames     Error E = joinErrors(make_error<CustomError>(7),
295f7f6d3e9SLang Hames                          make_error<CustomSubError>(42, 7));
296f7f6d3e9SLang Hames 
297f7f6d3e9SLang Hames     handleAllErrors(std::move(E),
298f7f6d3e9SLang Hames                     [&](const CustomSubError &SE) {
299f7f6d3e9SLang Hames                       CustomErrorInfo2 = SE.getInfo();
300f7f6d3e9SLang Hames                       CustomErrorExtraInfo = SE.getExtraInfo();
301f7f6d3e9SLang Hames                     },
302f7f6d3e9SLang Hames                     [&](const CustomError &CE) {
303f7f6d3e9SLang Hames                       // Assert that the CustomError instance above is handled
304f7f6d3e9SLang Hames                       // before the
305f7f6d3e9SLang Hames                       // CustomSubError - joinErrors should preserve error
306f7f6d3e9SLang Hames                       // ordering.
307f7f6d3e9SLang Hames                       EXPECT_EQ(CustomErrorInfo2, 0)
308f7f6d3e9SLang Hames                           << "CustomErrorInfo2 should be 0 here. "
309f7f6d3e9SLang Hames                              "joinErrors failed to preserve ordering.\n";
310f7f6d3e9SLang Hames                       CustomErrorInfo1 = CE.getInfo();
311f7f6d3e9SLang Hames                     });
312f7f6d3e9SLang Hames 
313f7f6d3e9SLang Hames     EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 &&
314f7f6d3e9SLang Hames                 CustomErrorExtraInfo == 7)
315f7f6d3e9SLang Hames         << "Failed handling compound Error.";
316f7f6d3e9SLang Hames   }
317f7f6d3e9SLang Hames 
318f7f6d3e9SLang Hames   // Test consumeError for both success and error cases.
319f7f6d3e9SLang Hames   {
320f7f6d3e9SLang Hames     Error E;
321f7f6d3e9SLang Hames     consumeError(std::move(E));
322f7f6d3e9SLang Hames   }
323f7f6d3e9SLang Hames   {
324f7f6d3e9SLang Hames     Error E = make_error<CustomError>(7);
325f7f6d3e9SLang Hames     consumeError(std::move(E));
326f7f6d3e9SLang Hames   }
327f7f6d3e9SLang Hames 
328f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is not caught.
329f7f6d3e9SLang Hames // Test runs in debug mode only.
330f7f6d3e9SLang Hames #ifndef NDEBUG
331f7f6d3e9SLang Hames   {
332f7f6d3e9SLang Hames     auto FailToHandle = []() {
333f7f6d3e9SLang Hames       handleAllErrors(make_error<CustomError>(7),
334f7f6d3e9SLang Hames                       [&](const CustomSubError &SE) {
335f7f6d3e9SLang Hames                         errs() << "This should never be called";
336f7f6d3e9SLang Hames                         exit(1);
337f7f6d3e9SLang Hames                       });
338f7f6d3e9SLang Hames     };
339f7f6d3e9SLang Hames 
340f7f6d3e9SLang Hames     EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:")
341f7f6d3e9SLang Hames         << "Unhandled Error in handleAllErrors call did not cause an "
342f7f6d3e9SLang Hames            "abort()";
343f7f6d3e9SLang Hames   }
344f7f6d3e9SLang Hames #endif
345f7f6d3e9SLang Hames 
346f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is returned from a
347f7f6d3e9SLang Hames // handler.
348f7f6d3e9SLang Hames // Test runs in debug mode only.
349f7f6d3e9SLang Hames #ifndef NDEBUG
350f7f6d3e9SLang Hames   {
351f7f6d3e9SLang Hames     auto ReturnErrorFromHandler = []() {
352f7f6d3e9SLang Hames       handleAllErrors(make_error<CustomError>(7),
353f7f6d3e9SLang Hames                       [&](std::unique_ptr<CustomSubError> SE) {
354f7f6d3e9SLang Hames                         return Error(std::move(SE));
355f7f6d3e9SLang Hames                       });
356f7f6d3e9SLang Hames     };
357f7f6d3e9SLang Hames 
358f7f6d3e9SLang Hames     EXPECT_DEATH(ReturnErrorFromHandler(),
359f7f6d3e9SLang Hames                  "Program aborted due to an unhandled Error:")
360f7f6d3e9SLang Hames         << " Error returned from handler in handleAllErrors call did not "
361f7f6d3e9SLang Hames            "cause abort()";
362f7f6d3e9SLang Hames   }
363f7f6d3e9SLang Hames #endif
364f7f6d3e9SLang Hames 
365f7f6d3e9SLang Hames   // Test that we can return values from handleErrors.
366f7f6d3e9SLang Hames   {
367f7f6d3e9SLang Hames     int ErrorInfo = 0;
368f7f6d3e9SLang Hames 
369f7f6d3e9SLang Hames     Error E = handleErrors(
370f7f6d3e9SLang Hames         make_error<CustomError>(7),
371f7f6d3e9SLang Hames         [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); });
372f7f6d3e9SLang Hames 
373f7f6d3e9SLang Hames     handleAllErrors(std::move(E),
374f7f6d3e9SLang Hames                     [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); });
375f7f6d3e9SLang Hames 
376f7f6d3e9SLang Hames     EXPECT_EQ(ErrorInfo, 7)
377f7f6d3e9SLang Hames         << "Failed to handle Error returned from handleErrors.";
378f7f6d3e9SLang Hames   }
379f7f6d3e9SLang Hames }
380f7f6d3e9SLang Hames 
381f7f6d3e9SLang Hames // Test Expected behavior.
382f7f6d3e9SLang Hames TEST(Error, CheckExpected) {
383f7f6d3e9SLang Hames 
384f7f6d3e9SLang Hames   // Check that non-errors convert to 'true'.
385f7f6d3e9SLang Hames   {
386f7f6d3e9SLang Hames     Expected<int> A = 7;
387f7f6d3e9SLang Hames     EXPECT_TRUE(!!A)
388f7f6d3e9SLang Hames         << "Expected with non-error value doesn't convert to 'true'";
389f7f6d3e9SLang Hames   }
390f7f6d3e9SLang Hames 
391f7f6d3e9SLang Hames   // Check that non-error values are accessible via operator*.
392f7f6d3e9SLang Hames   {
393f7f6d3e9SLang Hames     Expected<int> A = 7;
394f7f6d3e9SLang Hames     EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value";
395f7f6d3e9SLang Hames   }
396f7f6d3e9SLang Hames 
397f7f6d3e9SLang Hames   // Check that errors convert to 'false'.
398f7f6d3e9SLang Hames   {
399f7f6d3e9SLang Hames     Expected<int> A = make_error<CustomError>(42);
400f7f6d3e9SLang Hames     EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'";
401f7f6d3e9SLang Hames     consumeError(A.takeError());
402f7f6d3e9SLang Hames   }
403f7f6d3e9SLang Hames 
404f7f6d3e9SLang Hames   // Check that error values are accessible via takeError().
405f7f6d3e9SLang Hames   {
406f7f6d3e9SLang Hames     Expected<int> A = make_error<CustomError>(42);
407f7f6d3e9SLang Hames     Error E = A.takeError();
408f7f6d3e9SLang Hames     EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value";
409f7f6d3e9SLang Hames     consumeError(std::move(E));
410f7f6d3e9SLang Hames   }
411f7f6d3e9SLang Hames 
412f7f6d3e9SLang Hames // Check that an Expected instance with an error value doesn't allow access to
413f7f6d3e9SLang Hames // operator*.
414f7f6d3e9SLang Hames // Test runs in debug mode only.
415f7f6d3e9SLang Hames #ifndef NDEBUG
416f7f6d3e9SLang Hames   {
417f7f6d3e9SLang Hames     Expected<int> A = make_error<CustomError>(42);
4189fb8e1b2SLang Hames     EXPECT_DEATH(*A, "!HasError && \"Cannot get value when an error exists!\"")
419f7f6d3e9SLang Hames         << "Incorrect Expected error value";
420f7f6d3e9SLang Hames     consumeError(A.takeError());
421f7f6d3e9SLang Hames   }
422f7f6d3e9SLang Hames #endif
423f7f6d3e9SLang Hames 
424f7f6d3e9SLang Hames // Check that an Expected instance with an error triggers an abort if
425f7f6d3e9SLang Hames // unhandled.
426f7f6d3e9SLang Hames // Test runs in debug mode only.
427f7f6d3e9SLang Hames #ifndef NDEBUG
428f7f6d3e9SLang Hames   EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); },
429f7f6d3e9SLang Hames                "Program aborted due to an unhandled Error:")
430f7f6d3e9SLang Hames       << "Unchecked Expected<T> failure value did not cause an abort()";
431f7f6d3e9SLang Hames #endif
432f7f6d3e9SLang Hames 
433f7f6d3e9SLang Hames   // Test covariance of Expected.
434f7f6d3e9SLang Hames   {
435f7f6d3e9SLang Hames     class B {};
436f7f6d3e9SLang Hames     class D : public B {};
437f7f6d3e9SLang Hames 
438f7f6d3e9SLang Hames     Expected<B *> A1(Expected<D *>(nullptr));
439f7f6d3e9SLang Hames     A1 = Expected<D *>(nullptr);
440f7f6d3e9SLang Hames 
441f7f6d3e9SLang Hames     Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr));
442f7f6d3e9SLang Hames     A2 = Expected<std::unique_ptr<D>>(nullptr);
443f7f6d3e9SLang Hames   }
444f7f6d3e9SLang Hames }
445f7f6d3e9SLang Hames 
446f7f6d3e9SLang Hames TEST(Error, ECError) {
447f7f6d3e9SLang Hames 
448f7f6d3e9SLang Hames   // Round-trip a success value to check that it converts correctly.
449f7f6d3e9SLang Hames   EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())),
450f7f6d3e9SLang Hames             std::error_code())
451f7f6d3e9SLang Hames       << "std::error_code() should round-trip via Error conversions";
452f7f6d3e9SLang Hames 
453f7f6d3e9SLang Hames   // Round-trip an error value to check that it converts correctly.
454f7f6d3e9SLang Hames   EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)),
455f7f6d3e9SLang Hames             errc::invalid_argument)
456f7f6d3e9SLang Hames       << "std::error_code error value should round-trip via Error "
457f7f6d3e9SLang Hames          "conversions";
458f7f6d3e9SLang Hames }
459f7f6d3e9SLang Hames 
460f7f6d3e9SLang Hames } // end anon namespace
461