aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Support/ErrorTest.cpp
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2017-08-28 03:36:46 +0000
committerLang Hames <lhames@gmail.com>2017-08-28 03:36:46 +0000
commit5d06c23d4c0fad834dee33be780e980ac2ed0a30 (patch)
treece495d83f6988324be01432afd100b55ec0f261a /llvm/unittests/Support/ErrorTest.cpp
parent00b760ed48234e8884dc05eff321df203060b6da (diff)
downloadllvm-5d06c23d4c0fad834dee33be780e980ac2ed0a30.zip
llvm-5d06c23d4c0fad834dee33be780e980ac2ed0a30.tar.gz
llvm-5d06c23d4c0fad834dee33be780e980ac2ed0a30.tar.bz2
[Error] Add a handleExpected utility.
handleExpected is similar to handleErrors, but takes an Expected<T> as its first input value and a fallback functor as its second, followed by an arbitary list of error handlers (equivalent to the handler list of handleErrors). If the first input value is a success value then it is returned from handleErrors unmodified. Otherwise the contained error(s) are passed to handleErrors, along with the handlers. If handleErrors returns success (indicating that all errors have been handled) then handleExpected runs the fallback functor and returns its result. If handleErrors returns a failure value then the failure value is returned and the fallback functor is never run. This simplifies the process of re-trying operations that return Expected values. Without this utility such retry logic is cumbersome as the internal Error must be explicitly extracted from the Expected value, inspected to see if its handleable and then consumed: enum FooStrategy { Aggressive, Conservative }; Expected<Foo> tryFoo(FooStrategy S); Expected<Foo> Result; (void)!!Result; // "Check" Result so that it can be safely overwritten. if (auto ValOrErr = tryFoo(Aggressive)) Result = std::move(ValOrErr); else { auto Err = ValOrErr.takeError(); if (Err.isA<HandleableError>()) { consumeError(std::move(Err)); Result = tryFoo(Conservative); } else return std::move(Err); } with handleExpected, this can be re-written as: auto Result = handleExpected( tryFoo(Aggressive), []() { return tryFoo(Conservative); }, [](HandleableError&) { /* discard to handle */ }); llvm-svn: 311870
Diffstat (limited to 'llvm/unittests/Support/ErrorTest.cpp')
-rw-r--r--llvm/unittests/Support/ErrorTest.cpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/llvm/unittests/Support/ErrorTest.cpp b/llvm/unittests/Support/ErrorTest.cpp
index 852753f..db332eb 100644
--- a/llvm/unittests/Support/ErrorTest.cpp
+++ b/llvm/unittests/Support/ErrorTest.cpp
@@ -605,6 +605,59 @@ TEST(Error, ExpectedCovariance) {
(void)!!A2;
}
+// Test that handleExpected just returns success values.
+TEST(Error, HandleExpectedSuccess) {
+ auto ValOrErr =
+ handleExpected(Expected<int>(42),
+ []() { return Expected<int>(43); });
+ EXPECT_TRUE(!!ValOrErr)
+ << "handleExpected should have returned a success value here";
+ EXPECT_EQ(*ValOrErr, 42)
+ << "handleExpected should have returned the original success value here";
+}
+
+enum FooStrategy { Aggressive, Conservative };
+
+static Expected<int> foo(FooStrategy S) {
+ if (S == Aggressive)
+ return make_error<CustomError>(7);
+ return 42;
+}
+
+// Test that handleExpected invokes the error path if errors are not handled.
+TEST(Error, HandleExpectedUnhandledError) {
+ // foo(Aggressive) should return a CustomError which should pass through as
+ // there is no handler for CustomError.
+ auto ValOrErr =
+ handleExpected(
+ foo(Aggressive),
+ []() { return foo(Conservative); });
+
+ EXPECT_FALSE(!!ValOrErr)
+ << "handleExpected should have returned an error here";
+ auto Err = ValOrErr.takeError();
+ EXPECT_TRUE(Err.isA<CustomError>())
+ << "handleExpected should have returned the CustomError generated by "
+ "foo(Aggressive) here";
+ consumeError(std::move(Err));
+}
+
+// Test that handleExpected invokes the fallback path if errors are handled.
+TEST(Error, HandleExpectedHandledError) {
+ // foo(Aggressive) should return a CustomError which should handle triggering
+ // the fallback path.
+ auto ValOrErr =
+ handleExpected(
+ foo(Aggressive),
+ []() { return foo(Conservative); },
+ [](const CustomError&) { /* do nothing */ });
+
+ EXPECT_TRUE(!!ValOrErr)
+ << "handleExpected should have returned a success value here";
+ EXPECT_EQ(*ValOrErr, 42)
+ << "handleExpected returned the wrong success value";
+}
+
TEST(Error, ErrorCodeConversions) {
// Round-trip a success value to check that it converts correctly.
EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())),