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);
152f7f6d3e9SLang Hames 
153f7f6d3e9SLang Hames     EXPECT_TRUE(E.isA<CustomError>());
154f7f6d3e9SLang Hames     EXPECT_FALSE(E.isA<CustomSubError>());
155f7f6d3e9SLang Hames     EXPECT_TRUE(F.isA<CustomError>());
156f7f6d3e9SLang Hames     EXPECT_TRUE(F.isA<CustomSubError>());
157f7f6d3e9SLang Hames 
158f7f6d3e9SLang Hames     consumeError(std::move(E));
159f7f6d3e9SLang Hames     consumeError(std::move(F));
160f7f6d3e9SLang Hames   }
161f7f6d3e9SLang Hames 
162f7f6d3e9SLang Hames   // Check that we can handle a custom error.
163f7f6d3e9SLang Hames   {
164f7f6d3e9SLang Hames     int CaughtErrorInfo = 0;
165f7f6d3e9SLang Hames     handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) {
166f7f6d3e9SLang Hames       CaughtErrorInfo = CE.getInfo();
167f7f6d3e9SLang Hames     });
168f7f6d3e9SLang Hames 
169f7f6d3e9SLang Hames     EXPECT_TRUE(CaughtErrorInfo == 42)
170f7f6d3e9SLang Hames         << "Wrong result from CustomError handler";
171f7f6d3e9SLang Hames   }
172f7f6d3e9SLang Hames 
173f7f6d3e9SLang Hames   // Check that handler type deduction also works for handlers
174f7f6d3e9SLang Hames   // of the following types:
175f7f6d3e9SLang Hames   // void (const Err&)
176f7f6d3e9SLang Hames   // Error (const Err&) mutable
177f7f6d3e9SLang Hames   // void (const Err&) mutable
178f7f6d3e9SLang Hames   // Error (Err&)
179f7f6d3e9SLang Hames   // void (Err&)
180f7f6d3e9SLang Hames   // Error (Err&) mutable
181f7f6d3e9SLang Hames   // void (Err&) mutable
182f7f6d3e9SLang Hames   // Error (unique_ptr<Err>)
183f7f6d3e9SLang Hames   // void (unique_ptr<Err>)
184f7f6d3e9SLang Hames   // Error (unique_ptr<Err>) mutable
185f7f6d3e9SLang Hames   // void (unique_ptr<Err>) mutable
186f7f6d3e9SLang Hames 
187f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {});
188f7f6d3e9SLang Hames 
189f7f6d3e9SLang Hames   handleAllErrors(
190f7f6d3e9SLang Hames       make_error<CustomError>(42),
191f7f6d3e9SLang Hames       [](const CustomError &CE) mutable { return Error::success(); });
192f7f6d3e9SLang Hames 
193f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
194f7f6d3e9SLang Hames                   [](const CustomError &CE) mutable {});
195f7f6d3e9SLang Hames 
196f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
197f7f6d3e9SLang Hames                   [](CustomError &CE) { return Error::success(); });
198f7f6d3e9SLang Hames 
199f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {});
200f7f6d3e9SLang Hames 
201f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
202f7f6d3e9SLang Hames                   [](CustomError &CE) mutable { return Error::success(); });
203f7f6d3e9SLang Hames 
204f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {});
205f7f6d3e9SLang Hames 
206f7f6d3e9SLang Hames   handleAllErrors(
207f7f6d3e9SLang Hames       make_error<CustomError>(42),
208f7f6d3e9SLang Hames       [](std::unique_ptr<CustomError> CE) { return Error::success(); });
209f7f6d3e9SLang Hames 
210f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
211f7f6d3e9SLang Hames                   [](std::unique_ptr<CustomError> CE) {});
212f7f6d3e9SLang Hames 
213f7f6d3e9SLang Hames   handleAllErrors(
214f7f6d3e9SLang Hames       make_error<CustomError>(42),
215f7f6d3e9SLang Hames       [](std::unique_ptr<CustomError> CE) mutable { return Error::success(); });
216f7f6d3e9SLang Hames 
217f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42),
218f7f6d3e9SLang Hames                   [](std::unique_ptr<CustomError> CE) mutable {});
219f7f6d3e9SLang Hames 
220f7f6d3e9SLang Hames   // Check that named handlers of type 'Error (const Err&)' work.
221f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), handleCustomError);
222f7f6d3e9SLang Hames 
223f7f6d3e9SLang Hames   // Check that named handlers of type 'void (const Err&)' work.
224f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid);
225f7f6d3e9SLang Hames 
226f7f6d3e9SLang Hames   // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.
227f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP);
228f7f6d3e9SLang Hames 
229f7f6d3e9SLang Hames   // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.
230f7f6d3e9SLang Hames   handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid);
231f7f6d3e9SLang Hames 
232f7f6d3e9SLang Hames   // Check that we can handle a custom error with a custom base class.
233f7f6d3e9SLang Hames   {
234f7f6d3e9SLang Hames     int CaughtErrorInfo = 0;
235f7f6d3e9SLang Hames     int CaughtErrorExtraInfo = 0;
236f7f6d3e9SLang Hames     handleAllErrors(make_error<CustomSubError>(42, 7),
237f7f6d3e9SLang Hames                     [&](const CustomSubError &SE) {
238f7f6d3e9SLang Hames                       CaughtErrorInfo = SE.getInfo();
239f7f6d3e9SLang Hames                       CaughtErrorExtraInfo = SE.getExtraInfo();
240f7f6d3e9SLang Hames                     });
241f7f6d3e9SLang Hames 
242f7f6d3e9SLang Hames     EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7)
243f7f6d3e9SLang Hames         << "Wrong result from CustomSubError handler";
244f7f6d3e9SLang Hames   }
245f7f6d3e9SLang Hames 
246f7f6d3e9SLang Hames   // Check that we trigger only the first handler that applies.
247f7f6d3e9SLang Hames   {
248f7f6d3e9SLang Hames     int DummyInfo = 0;
249f7f6d3e9SLang Hames     int CaughtErrorInfo = 0;
250f7f6d3e9SLang Hames     int CaughtErrorExtraInfo = 0;
251f7f6d3e9SLang Hames 
252f7f6d3e9SLang Hames     handleAllErrors(make_error<CustomSubError>(42, 7),
253f7f6d3e9SLang Hames                     [&](const CustomSubError &SE) {
254f7f6d3e9SLang Hames                       CaughtErrorInfo = SE.getInfo();
255f7f6d3e9SLang Hames                       CaughtErrorExtraInfo = SE.getExtraInfo();
256f7f6d3e9SLang Hames                     },
257f7f6d3e9SLang Hames                     [&](const CustomError &CE) { DummyInfo = CE.getInfo(); });
258f7f6d3e9SLang Hames 
259f7f6d3e9SLang Hames     EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 &&
260f7f6d3e9SLang Hames                 DummyInfo == 0)
261f7f6d3e9SLang Hames         << "Activated the wrong Error handler(s)";
262f7f6d3e9SLang Hames   }
263f7f6d3e9SLang Hames 
264f7f6d3e9SLang Hames   // Check that general handlers shadow specific ones.
265f7f6d3e9SLang Hames   {
266f7f6d3e9SLang Hames     int CaughtErrorInfo = 0;
267f7f6d3e9SLang Hames     int DummyInfo = 0;
268f7f6d3e9SLang Hames     int DummyExtraInfo = 0;
269f7f6d3e9SLang Hames 
270f7f6d3e9SLang Hames     handleAllErrors(
271f7f6d3e9SLang Hames         make_error<CustomSubError>(42, 7),
272f7f6d3e9SLang Hames         [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); },
273f7f6d3e9SLang Hames         [&](const CustomSubError &SE) {
274f7f6d3e9SLang Hames           DummyInfo = SE.getInfo();
275f7f6d3e9SLang Hames           DummyExtraInfo = SE.getExtraInfo();
276f7f6d3e9SLang Hames         });
277f7f6d3e9SLang Hames 
278f7f6d3e9SLang Hames     EXPECT_TRUE(CaughtErrorInfo = 42 && DummyInfo == 0 && DummyExtraInfo == 0)
279f7f6d3e9SLang Hames         << "General Error handler did not shadow specific handler";
280f7f6d3e9SLang Hames   }
281f7f6d3e9SLang Hames }
282f7f6d3e9SLang Hames 
283f7f6d3e9SLang Hames // Test utility functions.
284f7f6d3e9SLang Hames TEST(Error, CheckErrorUtilities) {
285f7f6d3e9SLang Hames 
286f7f6d3e9SLang Hames   // Test joinErrors
287f7f6d3e9SLang Hames   {
288f7f6d3e9SLang Hames     int CustomErrorInfo1 = 0;
289f7f6d3e9SLang Hames     int CustomErrorInfo2 = 0;
290f7f6d3e9SLang Hames     int CustomErrorExtraInfo = 0;
291f7f6d3e9SLang Hames     Error E = joinErrors(make_error<CustomError>(7),
292f7f6d3e9SLang Hames                          make_error<CustomSubError>(42, 7));
293f7f6d3e9SLang Hames 
294f7f6d3e9SLang Hames     handleAllErrors(std::move(E),
295f7f6d3e9SLang Hames                     [&](const CustomSubError &SE) {
296f7f6d3e9SLang Hames                       CustomErrorInfo2 = SE.getInfo();
297f7f6d3e9SLang Hames                       CustomErrorExtraInfo = SE.getExtraInfo();
298f7f6d3e9SLang Hames                     },
299f7f6d3e9SLang Hames                     [&](const CustomError &CE) {
300f7f6d3e9SLang Hames                       // Assert that the CustomError instance above is handled
301f7f6d3e9SLang Hames                       // before the
302f7f6d3e9SLang Hames                       // CustomSubError - joinErrors should preserve error
303f7f6d3e9SLang Hames                       // ordering.
304f7f6d3e9SLang Hames                       EXPECT_EQ(CustomErrorInfo2, 0)
305f7f6d3e9SLang Hames                           << "CustomErrorInfo2 should be 0 here. "
306f7f6d3e9SLang Hames                              "joinErrors failed to preserve ordering.\n";
307f7f6d3e9SLang Hames                       CustomErrorInfo1 = CE.getInfo();
308f7f6d3e9SLang Hames                     });
309f7f6d3e9SLang Hames 
310f7f6d3e9SLang Hames     EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 &&
311f7f6d3e9SLang Hames                 CustomErrorExtraInfo == 7)
312f7f6d3e9SLang Hames         << "Failed handling compound Error.";
313f7f6d3e9SLang Hames   }
314f7f6d3e9SLang Hames 
315f7f6d3e9SLang Hames   // Test consumeError for both success and error cases.
316f7f6d3e9SLang Hames   {
317f7f6d3e9SLang Hames     Error E;
318f7f6d3e9SLang Hames     consumeError(std::move(E));
319f7f6d3e9SLang Hames   }
320f7f6d3e9SLang Hames   {
321f7f6d3e9SLang Hames     Error E = make_error<CustomError>(7);
322f7f6d3e9SLang Hames     consumeError(std::move(E));
323f7f6d3e9SLang Hames   }
324f7f6d3e9SLang Hames 
325f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is not caught.
326f7f6d3e9SLang Hames // Test runs in debug mode only.
327f7f6d3e9SLang Hames #ifndef NDEBUG
328f7f6d3e9SLang Hames   {
329f7f6d3e9SLang Hames     auto FailToHandle = []() {
330f7f6d3e9SLang Hames       handleAllErrors(make_error<CustomError>(7),
331f7f6d3e9SLang Hames                       [&](const CustomSubError &SE) {
332f7f6d3e9SLang Hames                         errs() << "This should never be called";
333f7f6d3e9SLang Hames                         exit(1);
334f7f6d3e9SLang Hames                       });
335f7f6d3e9SLang Hames     };
336f7f6d3e9SLang Hames 
337f7f6d3e9SLang Hames     EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:")
338f7f6d3e9SLang Hames         << "Unhandled Error in handleAllErrors call did not cause an "
339f7f6d3e9SLang Hames            "abort()";
340f7f6d3e9SLang Hames   }
341f7f6d3e9SLang Hames #endif
342f7f6d3e9SLang Hames 
343f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is returned from a
344f7f6d3e9SLang Hames // handler.
345f7f6d3e9SLang Hames // Test runs in debug mode only.
346f7f6d3e9SLang Hames #ifndef NDEBUG
347f7f6d3e9SLang Hames   {
348f7f6d3e9SLang Hames     auto ReturnErrorFromHandler = []() {
349f7f6d3e9SLang Hames       handleAllErrors(make_error<CustomError>(7),
350f7f6d3e9SLang Hames                       [&](std::unique_ptr<CustomSubError> SE) {
351f7f6d3e9SLang Hames                         return Error(std::move(SE));
352f7f6d3e9SLang Hames                       });
353f7f6d3e9SLang Hames     };
354f7f6d3e9SLang Hames 
355f7f6d3e9SLang Hames     EXPECT_DEATH(ReturnErrorFromHandler(),
356f7f6d3e9SLang Hames                  "Program aborted due to an unhandled Error:")
357f7f6d3e9SLang Hames         << " Error returned from handler in handleAllErrors call did not "
358f7f6d3e9SLang Hames            "cause abort()";
359f7f6d3e9SLang Hames   }
360f7f6d3e9SLang Hames #endif
361f7f6d3e9SLang Hames 
362f7f6d3e9SLang Hames   // Test that we can return values from handleErrors.
363f7f6d3e9SLang Hames   {
364f7f6d3e9SLang Hames     int ErrorInfo = 0;
365f7f6d3e9SLang Hames 
366f7f6d3e9SLang Hames     Error E = handleErrors(
367f7f6d3e9SLang Hames         make_error<CustomError>(7),
368f7f6d3e9SLang Hames         [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); });
369f7f6d3e9SLang Hames 
370f7f6d3e9SLang Hames     handleAllErrors(std::move(E),
371f7f6d3e9SLang Hames                     [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); });
372f7f6d3e9SLang Hames 
373f7f6d3e9SLang Hames     EXPECT_EQ(ErrorInfo, 7)
374f7f6d3e9SLang Hames         << "Failed to handle Error returned from handleErrors.";
375f7f6d3e9SLang Hames   }
376f7f6d3e9SLang Hames }
377f7f6d3e9SLang Hames 
378f7f6d3e9SLang Hames // Test Expected behavior.
379f7f6d3e9SLang Hames TEST(Error, CheckExpected) {
380f7f6d3e9SLang Hames 
381f7f6d3e9SLang Hames   // Check that non-errors convert to 'true'.
382f7f6d3e9SLang Hames   {
383f7f6d3e9SLang Hames     Expected<int> A = 7;
384f7f6d3e9SLang Hames     EXPECT_TRUE(!!A)
385f7f6d3e9SLang Hames         << "Expected with non-error value doesn't convert to 'true'";
386f7f6d3e9SLang Hames   }
387f7f6d3e9SLang Hames 
388f7f6d3e9SLang Hames   // Check that non-error values are accessible via operator*.
389f7f6d3e9SLang Hames   {
390f7f6d3e9SLang Hames     Expected<int> A = 7;
391f7f6d3e9SLang Hames     EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value";
392f7f6d3e9SLang Hames   }
393f7f6d3e9SLang Hames 
394f7f6d3e9SLang Hames   // Check that errors convert to 'false'.
395f7f6d3e9SLang Hames   {
396f7f6d3e9SLang Hames     Expected<int> A = make_error<CustomError>(42);
397f7f6d3e9SLang Hames     EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'";
398f7f6d3e9SLang Hames     consumeError(A.takeError());
399f7f6d3e9SLang Hames   }
400f7f6d3e9SLang Hames 
401f7f6d3e9SLang Hames   // Check that error values are accessible via takeError().
402f7f6d3e9SLang Hames   {
403f7f6d3e9SLang Hames     Expected<int> A = make_error<CustomError>(42);
404f7f6d3e9SLang Hames     Error E = A.takeError();
405f7f6d3e9SLang Hames     EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value";
406f7f6d3e9SLang Hames     consumeError(std::move(E));
407f7f6d3e9SLang Hames   }
408f7f6d3e9SLang Hames 
409f7f6d3e9SLang Hames // Check that an Expected instance with an error value doesn't allow access to
410f7f6d3e9SLang Hames // operator*.
411f7f6d3e9SLang Hames // Test runs in debug mode only.
412f7f6d3e9SLang Hames #ifndef NDEBUG
413f7f6d3e9SLang Hames   {
414f7f6d3e9SLang Hames     Expected<int> A = make_error<CustomError>(42);
415*9fb8e1b2SLang Hames     EXPECT_DEATH(*A, "!HasError && \"Cannot get value when an error exists!\"")
416f7f6d3e9SLang Hames         << "Incorrect Expected error value";
417f7f6d3e9SLang Hames     consumeError(A.takeError());
418f7f6d3e9SLang Hames   }
419f7f6d3e9SLang Hames #endif
420f7f6d3e9SLang Hames 
421f7f6d3e9SLang Hames // Check that an Expected instance with an error triggers an abort if
422f7f6d3e9SLang Hames // unhandled.
423f7f6d3e9SLang Hames // Test runs in debug mode only.
424f7f6d3e9SLang Hames #ifndef NDEBUG
425f7f6d3e9SLang Hames   EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); },
426f7f6d3e9SLang Hames                "Program aborted due to an unhandled Error:")
427f7f6d3e9SLang Hames       << "Unchecked Expected<T> failure value did not cause an abort()";
428f7f6d3e9SLang Hames #endif
429f7f6d3e9SLang Hames 
430f7f6d3e9SLang Hames   // Test covariance of Expected.
431f7f6d3e9SLang Hames   {
432f7f6d3e9SLang Hames     class B {};
433f7f6d3e9SLang Hames     class D : public B {};
434f7f6d3e9SLang Hames 
435f7f6d3e9SLang Hames     Expected<B *> A1(Expected<D *>(nullptr));
436f7f6d3e9SLang Hames     A1 = Expected<D *>(nullptr);
437f7f6d3e9SLang Hames 
438f7f6d3e9SLang Hames     Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr));
439f7f6d3e9SLang Hames     A2 = Expected<std::unique_ptr<D>>(nullptr);
440f7f6d3e9SLang Hames   }
441f7f6d3e9SLang Hames }
442f7f6d3e9SLang Hames 
443f7f6d3e9SLang Hames TEST(Error, ECError) {
444f7f6d3e9SLang Hames 
445f7f6d3e9SLang Hames   // Round-trip a success value to check that it converts correctly.
446f7f6d3e9SLang Hames   EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())),
447f7f6d3e9SLang Hames             std::error_code())
448f7f6d3e9SLang Hames       << "std::error_code() should round-trip via Error conversions";
449f7f6d3e9SLang Hames 
450f7f6d3e9SLang Hames   // Round-trip an error value to check that it converts correctly.
451f7f6d3e9SLang Hames   EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)),
452f7f6d3e9SLang Hames             errc::invalid_argument)
453f7f6d3e9SLang Hames       << "std::error_code error value should round-trip via Error "
454f7f6d3e9SLang Hames          "conversions";
455f7f6d3e9SLang Hames }
456f7f6d3e9SLang Hames 
457f7f6d3e9SLang Hames } // end anon namespace
458