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