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