1*810390e3Srobert //===-- error_test.cpp --sssssssss-----------------------------------------===//
2*810390e3Srobert //
3*810390e3Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*810390e3Srobert // See https://llvm.org/LICENSE.txt for license information.
5*810390e3Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*810390e3Srobert //
7*810390e3Srobert //===----------------------------------------------------------------------===//
8*810390e3Srobert //
9*810390e3Srobert // This file is a part of the ORC runtime.
10*810390e3Srobert //
11*810390e3Srobert // Note:
12*810390e3Srobert //   This unit test was adapted from
13*810390e3Srobert //   llvm/unittests/Support/ExtensibleRTTITest.cpp
14*810390e3Srobert //
15*810390e3Srobert //===----------------------------------------------------------------------===//
16*810390e3Srobert 
17*810390e3Srobert #include "error.h"
18*810390e3Srobert #include "gtest/gtest.h"
19*810390e3Srobert 
20*810390e3Srobert using namespace __orc_rt;
21*810390e3Srobert 
22*810390e3Srobert namespace {
23*810390e3Srobert 
24*810390e3Srobert class CustomError : public RTTIExtends<CustomError, ErrorInfoBase> {
25*810390e3Srobert public:
CustomError(int V1)26*810390e3Srobert   CustomError(int V1) : V1(V1) {}
toString() const27*810390e3Srobert   std::string toString() const override {
28*810390e3Srobert     return "CustomError V1 = " + std::to_string(V1);
29*810390e3Srobert   }
getV1() const30*810390e3Srobert   int getV1() const { return V1; }
31*810390e3Srobert 
32*810390e3Srobert protected:
33*810390e3Srobert   int V1;
34*810390e3Srobert };
35*810390e3Srobert 
36*810390e3Srobert class CustomSubError : public RTTIExtends<CustomSubError, CustomError> {
37*810390e3Srobert public:
CustomSubError(int V1,std::string V2)38*810390e3Srobert   CustomSubError(int V1, std::string V2)
39*810390e3Srobert       : RTTIExtends<CustomSubError, CustomError>(V1), V2(std::move(V2)) {}
toString() const40*810390e3Srobert   std::string toString() const override {
41*810390e3Srobert     return "CustomSubError V1 = " + std::to_string(V1) + ", " + V2;
42*810390e3Srobert   }
getV2() const43*810390e3Srobert   const std::string &getV2() const { return V2; }
44*810390e3Srobert 
45*810390e3Srobert protected:
46*810390e3Srobert   std::string V2;
47*810390e3Srobert };
48*810390e3Srobert 
49*810390e3Srobert } // end anonymous namespace
50*810390e3Srobert 
51*810390e3Srobert // Test that a checked success value doesn't cause any issues.
TEST(Error,CheckedSuccess)52*810390e3Srobert TEST(Error, CheckedSuccess) {
53*810390e3Srobert   Error E = Error::success();
54*810390e3Srobert   EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'";
55*810390e3Srobert }
56*810390e3Srobert 
57*810390e3Srobert // Check that a consumed success value doesn't cause any issues.
TEST(Error,ConsumeSuccess)58*810390e3Srobert TEST(Error, ConsumeSuccess) { consumeError(Error::success()); }
59*810390e3Srobert 
TEST(Error,ConsumeError)60*810390e3Srobert TEST(Error, ConsumeError) {
61*810390e3Srobert   Error E = make_error<CustomError>(42);
62*810390e3Srobert   if (E) {
63*810390e3Srobert     consumeError(std::move(E));
64*810390e3Srobert   } else
65*810390e3Srobert     ADD_FAILURE() << "Error failure value should convert to true";
66*810390e3Srobert }
67*810390e3Srobert 
68*810390e3Srobert // Test that unchecked success values cause an abort.
TEST(Error,UncheckedSuccess)69*810390e3Srobert TEST(Error, UncheckedSuccess) {
70*810390e3Srobert   EXPECT_DEATH({ Error E = Error::success(); },
71*810390e3Srobert                "Error must be checked prior to destruction")
72*810390e3Srobert       << "Unchecked Error Succes value did not cause abort()";
73*810390e3Srobert }
74*810390e3Srobert 
75*810390e3Srobert // Test that a checked but unhandled error causes an abort.
TEST(Error,CheckedButUnhandledError)76*810390e3Srobert TEST(Error, CheckedButUnhandledError) {
77*810390e3Srobert   auto DropUnhandledError = []() {
78*810390e3Srobert     Error E = make_error<CustomError>(42);
79*810390e3Srobert     (void)!E;
80*810390e3Srobert   };
81*810390e3Srobert   EXPECT_DEATH(DropUnhandledError(),
82*810390e3Srobert                "Error must be checked prior to destruction")
83*810390e3Srobert       << "Unhandled Error failure value did not cause an abort()";
84*810390e3Srobert }
85*810390e3Srobert 
86*810390e3Srobert // Test that error_cast works as expected.
TEST(Error,BasicErrorCast)87*810390e3Srobert TEST(Error, BasicErrorCast) {
88*810390e3Srobert   {
89*810390e3Srobert     // Check casting base error value to base error type.
90*810390e3Srobert     auto E = make_error<CustomError>(42);
91*810390e3Srobert     if (auto CSE = error_cast<CustomSubError>(E)) {
92*810390e3Srobert       ADD_FAILURE() << "Derived cast incorrectly matched base error";
93*810390e3Srobert     } else if (auto CE = error_cast<CustomError>(E)) {
94*810390e3Srobert       EXPECT_EQ(CE->getV1(), 42) << "Unexpected wrapped value";
95*810390e3Srobert     } else
96*810390e3Srobert       ADD_FAILURE() << "Unexpected error value";
97*810390e3Srobert   }
98*810390e3Srobert 
99*810390e3Srobert   {
100*810390e3Srobert     // Check casting derived error value to base error type.
101*810390e3Srobert     auto E = make_error<CustomSubError>(42, "foo");
102*810390e3Srobert     if (auto CE = error_cast<CustomError>(E)) {
103*810390e3Srobert       EXPECT_EQ(CE->getV1(), 42) << "Unexpected wrapped value";
104*810390e3Srobert     } else
105*810390e3Srobert       ADD_FAILURE() << "Unexpected error value";
106*810390e3Srobert   }
107*810390e3Srobert 
108*810390e3Srobert   {
109*810390e3Srobert     // Check casting derived error value to derived error type.
110*810390e3Srobert     auto E = make_error<CustomSubError>(42, "foo");
111*810390e3Srobert     if (auto CSE = error_cast<CustomSubError>(E)) {
112*810390e3Srobert       EXPECT_EQ(CSE->getV1(), 42) << "Unexpected wrapped value";
113*810390e3Srobert       EXPECT_EQ(CSE->getV2(), "foo") << "Unexpected wrapped value";
114*810390e3Srobert     } else
115*810390e3Srobert       ADD_FAILURE() << "Unexpected error value";
116*810390e3Srobert   }
117*810390e3Srobert }
118*810390e3Srobert 
119*810390e3Srobert // ErrorAsOutParameter tester.
errAsOutParamHelper(Error & Err)120*810390e3Srobert static void errAsOutParamHelper(Error &Err) {
121*810390e3Srobert   ErrorAsOutParameter ErrAsOutParam(&Err);
122*810390e3Srobert   // Verify that checked flag is raised - assignment should not crash.
123*810390e3Srobert   Err = Error::success();
124*810390e3Srobert   // Raise the checked bit manually - caller should still have to test the
125*810390e3Srobert   // error.
126*810390e3Srobert   (void)!!Err;
127*810390e3Srobert }
128*810390e3Srobert 
129*810390e3Srobert // Test that ErrorAsOutParameter sets the checked flag on construction.
TEST(Error,ErrorAsOutParameterChecked)130*810390e3Srobert TEST(Error, ErrorAsOutParameterChecked) {
131*810390e3Srobert   Error E = Error::success();
132*810390e3Srobert   errAsOutParamHelper(E);
133*810390e3Srobert   (void)!!E;
134*810390e3Srobert }
135*810390e3Srobert 
136*810390e3Srobert // Test that ErrorAsOutParameter clears the checked flag on destruction.
TEST(Error,ErrorAsOutParameterUnchecked)137*810390e3Srobert TEST(Error, ErrorAsOutParameterUnchecked) {
138*810390e3Srobert   EXPECT_DEATH(
139*810390e3Srobert       {
140*810390e3Srobert         Error E = Error::success();
141*810390e3Srobert         errAsOutParamHelper(E);
142*810390e3Srobert       },
143*810390e3Srobert       "Error must be checked prior to destruction")
144*810390e3Srobert       << "ErrorAsOutParameter did not clear the checked flag on destruction.";
145*810390e3Srobert }
146*810390e3Srobert 
147*810390e3Srobert // Check 'Error::isA<T>' method handling.
TEST(Error,IsAHandling)148*810390e3Srobert TEST(Error, IsAHandling) {
149*810390e3Srobert   // Check 'isA' handling.
150*810390e3Srobert   Error E = make_error<CustomError>(42);
151*810390e3Srobert   Error F = make_error<CustomSubError>(42, "foo");
152*810390e3Srobert   Error G = Error::success();
153*810390e3Srobert 
154*810390e3Srobert   EXPECT_TRUE(E.isA<CustomError>());
155*810390e3Srobert   EXPECT_FALSE(E.isA<CustomSubError>());
156*810390e3Srobert   EXPECT_TRUE(F.isA<CustomError>());
157*810390e3Srobert   EXPECT_TRUE(F.isA<CustomSubError>());
158*810390e3Srobert   EXPECT_FALSE(G.isA<CustomError>());
159*810390e3Srobert 
160*810390e3Srobert   consumeError(std::move(E));
161*810390e3Srobert   consumeError(std::move(F));
162*810390e3Srobert   consumeError(std::move(G));
163*810390e3Srobert }
164*810390e3Srobert 
TEST(Error,StringError)165*810390e3Srobert TEST(Error, StringError) {
166*810390e3Srobert   auto E = make_error<StringError>("foo");
167*810390e3Srobert   if (auto SE = error_cast<StringError>(E)) {
168*810390e3Srobert     EXPECT_EQ(SE->toString(), "foo") << "Unexpected StringError value";
169*810390e3Srobert   } else
170*810390e3Srobert     ADD_FAILURE() << "Expected StringError value";
171*810390e3Srobert }
172*810390e3Srobert 
173*810390e3Srobert // Test Checked Expected<T> in success mode.
TEST(Error,CheckedExpectedInSuccessMode)174*810390e3Srobert TEST(Error, CheckedExpectedInSuccessMode) {
175*810390e3Srobert   Expected<int> A = 7;
176*810390e3Srobert   EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'";
177*810390e3Srobert   // Access is safe in second test, since we checked the error in the first.
178*810390e3Srobert   EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value";
179*810390e3Srobert }
180*810390e3Srobert 
181*810390e3Srobert // Test Expected with reference type.
TEST(Error,ExpectedWithReferenceType)182*810390e3Srobert TEST(Error, ExpectedWithReferenceType) {
183*810390e3Srobert   int A = 7;
184*810390e3Srobert   Expected<int &> B = A;
185*810390e3Srobert   // 'Check' B.
186*810390e3Srobert   (void)!!B;
187*810390e3Srobert   int &C = *B;
188*810390e3Srobert   EXPECT_EQ(&A, &C) << "Expected failed to propagate reference";
189*810390e3Srobert }
190*810390e3Srobert 
191*810390e3Srobert // Test Unchecked Expected<T> in success mode.
192*810390e3Srobert // We expect this to blow up the same way Error would.
193*810390e3Srobert // Test runs in debug mode only.
TEST(Error,UncheckedExpectedInSuccessModeDestruction)194*810390e3Srobert TEST(Error, UncheckedExpectedInSuccessModeDestruction) {
195*810390e3Srobert   EXPECT_DEATH({ Expected<int> A = 7; },
196*810390e3Srobert                "Expected<T> must be checked before access or destruction.")
197*810390e3Srobert       << "Unchecekd Expected<T> success value did not cause an abort().";
198*810390e3Srobert }
199*810390e3Srobert 
200*810390e3Srobert // Test Unchecked Expected<T> in success mode.
201*810390e3Srobert // We expect this to blow up the same way Error would.
202*810390e3Srobert // Test runs in debug mode only.
TEST(Error,UncheckedExpectedInSuccessModeAccess)203*810390e3Srobert TEST(Error, UncheckedExpectedInSuccessModeAccess) {
204*810390e3Srobert   EXPECT_DEATH(
205*810390e3Srobert       {
206*810390e3Srobert         Expected<int> A = 7;
207*810390e3Srobert         *A;
208*810390e3Srobert       },
209*810390e3Srobert       "Expected<T> must be checked before access or destruction.")
210*810390e3Srobert       << "Unchecekd Expected<T> success value did not cause an abort().";
211*810390e3Srobert }
212*810390e3Srobert 
213*810390e3Srobert // Test Unchecked Expected<T> in success mode.
214*810390e3Srobert // We expect this to blow up the same way Error would.
215*810390e3Srobert // Test runs in debug mode only.
TEST(Error,UncheckedExpectedInSuccessModeAssignment)216*810390e3Srobert TEST(Error, UncheckedExpectedInSuccessModeAssignment) {
217*810390e3Srobert   EXPECT_DEATH(
218*810390e3Srobert       {
219*810390e3Srobert         Expected<int> A = 7;
220*810390e3Srobert         A = 7;
221*810390e3Srobert       },
222*810390e3Srobert       "Expected<T> must be checked before access or destruction.")
223*810390e3Srobert       << "Unchecekd Expected<T> success value did not cause an abort().";
224*810390e3Srobert }
225*810390e3Srobert 
226*810390e3Srobert // Test Expected<T> in failure mode.
TEST(Error,ExpectedInFailureMode)227*810390e3Srobert TEST(Error, ExpectedInFailureMode) {
228*810390e3Srobert   Expected<int> A = make_error<CustomError>(42);
229*810390e3Srobert   EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'";
230*810390e3Srobert   Error E = A.takeError();
231*810390e3Srobert   EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value";
232*810390e3Srobert   consumeError(std::move(E));
233*810390e3Srobert }
234*810390e3Srobert 
235*810390e3Srobert // Check that an Expected instance with an error value doesn't allow access to
236*810390e3Srobert // operator*.
237*810390e3Srobert // Test runs in debug mode only.
TEST(Error,AccessExpectedInFailureMode)238*810390e3Srobert TEST(Error, AccessExpectedInFailureMode) {
239*810390e3Srobert   Expected<int> A = make_error<CustomError>(42);
240*810390e3Srobert   EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.")
241*810390e3Srobert       << "Incorrect Expected error value";
242*810390e3Srobert   consumeError(A.takeError());
243*810390e3Srobert }
244*810390e3Srobert 
245*810390e3Srobert // Check that an Expected instance with an error triggers an abort if
246*810390e3Srobert // unhandled.
247*810390e3Srobert // Test runs in debug mode only.
TEST(Error,UnhandledExpectedInFailureMode)248*810390e3Srobert TEST(Error, UnhandledExpectedInFailureMode) {
249*810390e3Srobert   EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); },
250*810390e3Srobert                "Expected<T> must be checked before access or destruction.")
251*810390e3Srobert       << "Unchecked Expected<T> failure value did not cause an abort()";
252*810390e3Srobert }
253*810390e3Srobert 
254*810390e3Srobert // Test covariance of Expected.
TEST(Error,ExpectedCovariance)255*810390e3Srobert TEST(Error, ExpectedCovariance) {
256*810390e3Srobert   class B {};
257*810390e3Srobert   class D : public B {};
258*810390e3Srobert 
259*810390e3Srobert   Expected<B *> A1(Expected<D *>(nullptr));
260*810390e3Srobert   // Check A1 by converting to bool before assigning to it.
261*810390e3Srobert   (void)!!A1;
262*810390e3Srobert   A1 = Expected<D *>(nullptr);
263*810390e3Srobert   // Check A1 again before destruction.
264*810390e3Srobert   (void)!!A1;
265*810390e3Srobert 
266*810390e3Srobert   Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr));
267*810390e3Srobert   // Check A2 by converting to bool before assigning to it.
268*810390e3Srobert   (void)!!A2;
269*810390e3Srobert   A2 = Expected<std::unique_ptr<D>>(nullptr);
270*810390e3Srobert   // Check A2 again before destruction.
271*810390e3Srobert   (void)!!A2;
272*810390e3Srobert }
273*810390e3Srobert 
274*810390e3Srobert // Test that the ExitOnError utility works as expected.
TEST(Error,CantFailSuccess)275*810390e3Srobert TEST(Error, CantFailSuccess) {
276*810390e3Srobert   cantFail(Error::success());
277*810390e3Srobert 
278*810390e3Srobert   int X = cantFail(Expected<int>(42));
279*810390e3Srobert   EXPECT_EQ(X, 42) << "Expected value modified by cantFail";
280*810390e3Srobert 
281*810390e3Srobert   int Dummy = 42;
282*810390e3Srobert   int &Y = cantFail(Expected<int &>(Dummy));
283*810390e3Srobert   EXPECT_EQ(&Dummy, &Y) << "Reference mangled by cantFail";
284*810390e3Srobert }
285*810390e3Srobert 
286*810390e3Srobert // Test that cantFail results in a crash if you pass it a failure value.
TEST(Error,CantFailDeath)287*810390e3Srobert TEST(Error, CantFailDeath) {
288*810390e3Srobert   EXPECT_DEATH(cantFail(make_error<StringError>("foo")),
289*810390e3Srobert                "cantFail called on failure value")
290*810390e3Srobert       << "cantFail(Error) did not cause an abort for failure value";
291*810390e3Srobert 
292*810390e3Srobert   EXPECT_DEATH(cantFail(Expected<int>(make_error<StringError>("foo"))),
293*810390e3Srobert                "cantFail called on failure value")
294*810390e3Srobert       << "cantFail(Expected<int>) did not cause an abort for failure value";
295*810390e3Srobert }
296