[llvm] r263768 - [Support] Refactor Error unit tests to avoid duplicating work.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 17 17:12:38 PDT 2016


Author: lhames
Date: Thu Mar 17 19:12:37 2016
New Revision: 263768

URL: http://llvm.org/viewvc/llvm-project?rev=263768&view=rev
Log:
[Support] Refactor Error unit tests to avoid duplicating work.

Suggested by Dave Blaikie in review for r263749. Thanks Dave!


Modified:
    llvm/trunk/unittests/Support/ErrorTest.cpp

Modified: llvm/trunk/unittests/Support/ErrorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ErrorTest.cpp?rev=263768&r1=263767&r2=263768&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/ErrorTest.cpp (original)
+++ llvm/trunk/unittests/Support/ErrorTest.cpp Thu Mar 17 19:12:37 2016
@@ -16,43 +16,6 @@ using namespace llvm;
 
 namespace {
 
-// Test:
-//
-// Constructing success.
-//   - Silent acceptance of tested success.
-//   - Programmatic error on untested success.
-//
-// Custom error class.
-//   - Creation of a custom error class with a default base class.
-//   - Handling of a custom error class with a default base class.
-//   - Handler type deduction.
-//   - Failure to handle a custom error class.
-//   - Isa testing of a custom error class.
-//
-//   - Creation of a custom error class with a custom base class.
-//   - Handling of a custom error class with a default base class.
-//   - Correct shadowing of handlers.
-//
-// Utility functions:
-//   - join_errors to defer errors.
-//   - consume_error to consume a "safe" error without any output.
-//   - handleAllUnhandledErrors to assert that all errors are handled.
-//   - logAllUnhandledErrors to log errors to a stream.
-//   - ExitOnError tests.
-//
-// Expected tests:
-//   - Expected<T> with T.
-//   - Expected<T> with Error.
-//   - Failure to handle an Expected<T> in failure mode.
-//   - Error extraction (Expected -> Error).
-//
-// std::error_code:
-//   - std::error_code to Error in success mode.
-//   - std::error_code to Error (ECError) in failure mode.
-//   - Error to std::error_code in success mode.
-//   - Error (ECError) to std::error_code in failure mode.
-//
-
 // Custom error class with a default base class and some random 'info' attached.
 class CustomError : public ErrorInfo<CustomError> {
 public:
@@ -98,28 +61,6 @@ protected:
   int ExtraInfo;
 };
 
-// Verify that success values that are checked (i.e. cast to 'bool') are
-// destructed without error, and that unchecked success values cause an
-// abort.
-TEST(Error, CheckSuccess) {
-  // Test checked success.
-  {
-    Error E;
-    EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'";
-  }
-
-// Test unchecked success.
-// Test runs in debug mode only.
-#ifndef NDEBUG
-  {
-    auto DropUncheckedSuccess = []() { Error E; };
-    EXPECT_DEATH(DropUncheckedSuccess(),
-                 "Program aborted due to an unhandled Error:")
-        << "Unchecked Error Succes value did not cause abort()";
-  }
-#endif
-}
-
 static Error handleCustomError(const CustomError &CE) { return Error(); }
 
 static void handleCustomErrorVoid(const CustomError &CE) {}
@@ -130,64 +71,78 @@ static Error handleCustomErrorUP(std::un
 
 static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {}
 
-// Verify creation and handling of custom error classes.
-TEST(Error, CheckCustomErrors) {
+// Test that success values implicitly convert to false, and don't cause crashes
+// once they've been implicitly converted.
+TEST(Error, CheckedSuccess) {
+  Error E;
+  EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'";
+}
+
+// Test that unchecked succes values cause an abort.
+#ifndef NDEBUG
+TEST(Error, UncheckedSuccess) {
+  EXPECT_DEATH({ Error E; }, "Program aborted due to an unhandled Error:")
+      << "Unchecked Error Succes value did not cause abort()";
+}
+#endif
+
 // Check that we abort on unhandled failure cases. (Force conversion to bool
 // to make sure that we don't accidentally treat checked errors as handled).
 // Test runs in debug mode only.
 #ifndef NDEBUG
-  {
-    auto DropUnhandledError = []() {
-      Error E = make_error<CustomError>(42);
-      (void)!E;
-    };
-    EXPECT_DEATH(DropUnhandledError(),
-                 "Program aborted due to an unhandled Error:")
-        << "Unhandled Error failure value did not cause abort()";
-  }
+TEST(Error, UncheckedError) {
+  auto DropUnhandledError = []() {
+    Error E = make_error<CustomError>(42);
+    (void)!E;
+  };
+  EXPECT_DEATH(DropUnhandledError(),
+               "Program aborted due to an unhandled Error:")
+      << "Unhandled Error failure value did not cause abort()";
+}
 #endif
 
+// Check 'Error::isA<T>' method handling.
+TEST(Error, IsAHandling) {
   // Check 'isA' handling.
-  {
-    Error E = make_error<CustomError>(1);
-    Error F = make_error<CustomSubError>(1, 2);
-    Error G = Error::success();
-
-    EXPECT_TRUE(E.isA<CustomError>());
-    EXPECT_FALSE(E.isA<CustomSubError>());
-    EXPECT_TRUE(F.isA<CustomError>());
-    EXPECT_TRUE(F.isA<CustomSubError>());
-    EXPECT_FALSE(G.isA<CustomError>());
-
-    consumeError(std::move(E));
-    consumeError(std::move(F));
-    consumeError(std::move(G));
-  }
+  Error E = make_error<CustomError>(1);
+  Error F = make_error<CustomSubError>(1, 2);
+  Error G = Error::success();
+
+  EXPECT_TRUE(E.isA<CustomError>());
+  EXPECT_FALSE(E.isA<CustomSubError>());
+  EXPECT_TRUE(F.isA<CustomError>());
+  EXPECT_TRUE(F.isA<CustomSubError>());
+  EXPECT_FALSE(G.isA<CustomError>());
+
+  consumeError(std::move(E));
+  consumeError(std::move(F));
+  consumeError(std::move(G));
+}
 
-  // Check that we can handle a custom error.
-  {
-    int CaughtErrorInfo = 0;
-    handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) {
-      CaughtErrorInfo = CE.getInfo();
-    });
+// Check that we can handle a custom error.
+TEST(Error, HandleCustomError) {
+  int CaughtErrorInfo = 0;
+  handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) {
+    CaughtErrorInfo = CE.getInfo();
+  });
 
-    EXPECT_TRUE(CaughtErrorInfo == 42)
-        << "Wrong result from CustomError handler";
-  }
+  EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler";
+}
 
-  // Check that handler type deduction also works for handlers
-  // of the following types:
-  // void (const Err&)
-  // Error (const Err&) mutable
-  // void (const Err&) mutable
-  // Error (Err&)
-  // void (Err&)
-  // Error (Err&) mutable
-  // void (Err&) mutable
-  // Error (unique_ptr<Err>)
-  // void (unique_ptr<Err>)
-  // Error (unique_ptr<Err>) mutable
-  // void (unique_ptr<Err>) mutable
+// Check that handler type deduction also works for handlers
+// of the following types:
+// void (const Err&)
+// Error (const Err&) mutable
+// void (const Err&) mutable
+// Error (Err&)
+// void (Err&)
+// Error (Err&) mutable
+// void (Err&) mutable
+// Error (unique_ptr<Err>)
+// void (unique_ptr<Err>)
+// Error (unique_ptr<Err>) mutable
+// void (unique_ptr<Err>) mutable
+TEST(Error, HandlerTypeDeduction) {
 
   handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {});
 
@@ -233,246 +188,226 @@ TEST(Error, CheckCustomErrors) {
 
   // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.
   handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid);
+}
 
-  // Check that we can handle a custom error with a custom base class.
-  {
-    int CaughtErrorInfo = 0;
-    int CaughtErrorExtraInfo = 0;
-    handleAllErrors(make_error<CustomSubError>(42, 7),
-                    [&](const CustomSubError &SE) {
-                      CaughtErrorInfo = SE.getInfo();
-                      CaughtErrorExtraInfo = SE.getExtraInfo();
-                    });
+// Test that we can handle errors with custom base classes.
+TEST(Error, HandleCustomErrorWithCustomBaseClass) {
+  int CaughtErrorInfo = 0;
+  int CaughtErrorExtraInfo = 0;
+  handleAllErrors(make_error<CustomSubError>(42, 7),
+                  [&](const CustomSubError &SE) {
+                    CaughtErrorInfo = SE.getInfo();
+                    CaughtErrorExtraInfo = SE.getExtraInfo();
+                  });
 
-    EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7)
-        << "Wrong result from CustomSubError handler";
-  }
+  EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7)
+      << "Wrong result from CustomSubError handler";
+}
 
-  // Check that we trigger only the first handler that applies.
-  {
-    int DummyInfo = 0;
-    int CaughtErrorInfo = 0;
-    int CaughtErrorExtraInfo = 0;
-
-    handleAllErrors(make_error<CustomSubError>(42, 7),
-                    [&](const CustomSubError &SE) {
-                      CaughtErrorInfo = SE.getInfo();
-                      CaughtErrorExtraInfo = SE.getExtraInfo();
-                    },
-                    [&](const CustomError &CE) { DummyInfo = CE.getInfo(); });
-
-    EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 &&
-                DummyInfo == 0)
-        << "Activated the wrong Error handler(s)";
-  }
+// Check that we trigger only the first handler that applies.
+TEST(Error, FirstHandlerOnly) {
+  int DummyInfo = 0;
+  int CaughtErrorInfo = 0;
+  int CaughtErrorExtraInfo = 0;
+
+  handleAllErrors(make_error<CustomSubError>(42, 7),
+                  [&](const CustomSubError &SE) {
+                    CaughtErrorInfo = SE.getInfo();
+                    CaughtErrorExtraInfo = SE.getExtraInfo();
+                  },
+                  [&](const CustomError &CE) { DummyInfo = CE.getInfo(); });
+
+  EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 &&
+              DummyInfo == 0)
+      << "Activated the wrong Error handler(s)";
+}
 
-  // Check that general handlers shadow specific ones.
-  {
-    int CaughtErrorInfo = 0;
-    int DummyInfo = 0;
-    int DummyExtraInfo = 0;
-
-    handleAllErrors(
-        make_error<CustomSubError>(42, 7),
-        [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); },
-        [&](const CustomSubError &SE) {
-          DummyInfo = SE.getInfo();
-          DummyExtraInfo = SE.getExtraInfo();
-        });
+// Check that general handlers shadow specific ones.
+TEST(Error, HandlerShadowing) {
+  int CaughtErrorInfo = 0;
+  int DummyInfo = 0;
+  int DummyExtraInfo = 0;
 
-    EXPECT_TRUE(CaughtErrorInfo = 42 && DummyInfo == 0 && DummyExtraInfo == 0)
-        << "General Error handler did not shadow specific handler";
-  }
-}
+  handleAllErrors(
+      make_error<CustomSubError>(42, 7),
+      [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); },
+      [&](const CustomSubError &SE) {
+        DummyInfo = SE.getInfo();
+        DummyExtraInfo = SE.getExtraInfo();
+      });
 
-// Test utility functions.
-TEST(Error, CheckErrorUtilities) {
+  EXPECT_TRUE(CaughtErrorInfo = 42 && DummyInfo == 0 && DummyExtraInfo == 0)
+      << "General Error handler did not shadow specific handler";
+}
 
-  // Test joinErrors
-  {
-    int CustomErrorInfo1 = 0;
-    int CustomErrorInfo2 = 0;
-    int CustomErrorExtraInfo = 0;
-    Error E = joinErrors(make_error<CustomError>(7),
-                         make_error<CustomSubError>(42, 7));
-
-    handleAllErrors(std::move(E),
-                    [&](const CustomSubError &SE) {
-                      CustomErrorInfo2 = SE.getInfo();
-                      CustomErrorExtraInfo = SE.getExtraInfo();
-                    },
-                    [&](const CustomError &CE) {
-                      // Assert that the CustomError instance above is handled
-                      // before the
-                      // CustomSubError - joinErrors should preserve error
-                      // ordering.
-                      EXPECT_EQ(CustomErrorInfo2, 0)
-                          << "CustomErrorInfo2 should be 0 here. "
-                             "joinErrors failed to preserve ordering.\n";
-                      CustomErrorInfo1 = CE.getInfo();
-                    });
+// Test joinErrors.
+TEST(Error, CheckJoinErrors) {
+  int CustomErrorInfo1 = 0;
+  int CustomErrorInfo2 = 0;
+  int CustomErrorExtraInfo = 0;
+  Error E =
+      joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7));
+
+  handleAllErrors(std::move(E),
+                  [&](const CustomSubError &SE) {
+                    CustomErrorInfo2 = SE.getInfo();
+                    CustomErrorExtraInfo = SE.getExtraInfo();
+                  },
+                  [&](const CustomError &CE) {
+                    // Assert that the CustomError instance above is handled
+                    // before the
+                    // CustomSubError - joinErrors should preserve error
+                    // ordering.
+                    EXPECT_EQ(CustomErrorInfo2, 0)
+                        << "CustomErrorInfo2 should be 0 here. "
+                           "joinErrors failed to preserve ordering.\n";
+                    CustomErrorInfo1 = CE.getInfo();
+                  });
+
+  EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 &&
+              CustomErrorExtraInfo == 7)
+      << "Failed handling compound Error.";
+}
 
-    EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 &&
-                CustomErrorExtraInfo == 7)
-        << "Failed handling compound Error.";
-  }
+// Test that we can consume success values.
+TEST(Error, ConsumeSuccess) {
+  Error E;
+  consumeError(std::move(E));
+}
 
-  // Test consumeError for both success and error cases.
-  {
-    Error E;
-    consumeError(std::move(E));
-  }
-  {
-    Error E = make_error<CustomError>(7);
-    consumeError(std::move(E));
-  }
+TEST(Error, ConsumeError) {
+  Error E = make_error<CustomError>(7);
+  consumeError(std::move(E));
+}
 
 // Test that handleAllUnhandledErrors crashes if an error is not caught.
 // Test runs in debug mode only.
 #ifndef NDEBUG
-  {
-    auto FailToHandle = []() {
-      handleAllErrors(make_error<CustomError>(7),
-                      [&](const CustomSubError &SE) {
-                        errs() << "This should never be called";
-                        exit(1);
-                      });
-    };
-
-    EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:")
-        << "Unhandled Error in handleAllErrors call did not cause an "
-           "abort()";
-  }
+TEST(Error, FailureToHandle) {
+  auto FailToHandle = []() {
+    handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) {
+      errs() << "This should never be called";
+      exit(1);
+    });
+  };
+
+  EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:")
+      << "Unhandled Error in handleAllErrors call did not cause an "
+         "abort()";
+}
 #endif
 
 // Test that handleAllUnhandledErrors crashes if an error is returned from a
 // handler.
 // Test runs in debug mode only.
 #ifndef NDEBUG
-  {
-    auto ReturnErrorFromHandler = []() {
-      handleAllErrors(make_error<CustomError>(7),
-                      [&](std::unique_ptr<CustomSubError> SE) {
-                        return Error(std::move(SE));
-                      });
-    };
-
-    EXPECT_DEATH(ReturnErrorFromHandler(),
-                 "Program aborted due to an unhandled Error:")
-        << " Error returned from handler in handleAllErrors call did not "
-           "cause abort()";
-  }
-#endif
+TEST(Error, FailureFromHandler) {
+  auto ReturnErrorFromHandler = []() {
+    handleAllErrors(make_error<CustomError>(7),
+                    [&](std::unique_ptr<CustomSubError> SE) {
+                      return Error(std::move(SE));
+                    });
+  };
 
-  // Test that we can return values from handleErrors.
-  {
-    int ErrorInfo = 0;
-
-    Error E = handleErrors(
-        make_error<CustomError>(7),
-        [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); });
+  EXPECT_DEATH(ReturnErrorFromHandler(),
+               "Program aborted due to an unhandled Error:")
+      << " Error returned from handler in handleAllErrors call did not "
+         "cause abort()";
+}
+#endif
 
-    handleAllErrors(std::move(E),
-                    [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); });
+// Test that we can return values from handleErrors.
+TEST(Error, CatchErrorFromHandler) {
+  int ErrorInfo = 0;
+
+  Error E = handleErrors(
+      make_error<CustomError>(7),
+      [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); });
 
-    EXPECT_EQ(ErrorInfo, 7)
-        << "Failed to handle Error returned from handleErrors.";
-  }
+  handleAllErrors(std::move(E),
+                  [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); });
 
-  // Test ExitOnError
-  {
-    ExitOnError ExitOnErr;
-    ExitOnErr.setBanner("Error in tool:");
-    ExitOnErr.setExitCodeMapper(
-      [](const Error &E) {
-        if (E.isA<CustomSubError>())
-          return 2;
-        return 1;
-      });
+  EXPECT_EQ(ErrorInfo, 7)
+      << "Failed to handle Error returned from handleErrors.";
+}
 
-    // Make sure we don't bail on success.
-    ExitOnErr(Error::success());
-    EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7)
+// Test that the ExitOnError utility works as expected.
+TEST(Error, ExitOnError) {
+  ExitOnError ExitOnErr;
+  ExitOnErr.setBanner("Error in tool:");
+  ExitOnErr.setExitCodeMapper([](const Error &E) {
+    if (E.isA<CustomSubError>())
+      return 2;
+    return 1;
+  });
+
+  // Make sure we don't bail on success.
+  ExitOnErr(Error::success());
+  EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7)
       << "exitOnError returned an invalid value for Expected";
 
-    // Exit tests.
-    EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)),
-                ::testing::ExitedWithCode(1), "Error in tool:")
+  // Exit tests.
+  EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)),
+              ::testing::ExitedWithCode(1), "Error in tool:")
       << "exitOnError returned an unexpected error result";
 
-    EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))),
-                ::testing::ExitedWithCode(2), "Error in tool:")
+  EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))),
+              ::testing::ExitedWithCode(2), "Error in tool:")
       << "exitOnError returned an unexpected error result";
-  }
 }
 
-// Test Expected behavior.
-TEST(Error, CheckExpected) {
-
-  // Check that non-errors convert to 'true'.
-  {
-    Expected<int> A = 7;
-    EXPECT_TRUE(!!A)
-        << "Expected with non-error value doesn't convert to 'true'";
-  }
-
-  // Check that non-error values are accessible via operator*.
-  {
-    Expected<int> A = 7;
-    EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value";
-  }
-
-  // Check that errors convert to 'false'.
-  {
-    Expected<int> A = make_error<CustomError>(42);
-    EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'";
-    consumeError(A.takeError());
-  }
+// Test Expected<T> in success mode.
+TEST(Error, ExpectedInSuccessMode) {
+  Expected<int> A = 7;
+  EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'";
+  EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value";
+}
 
-  // Check that error values are accessible via takeError().
-  {
-    Expected<int> A = make_error<CustomError>(42);
-    Error E = A.takeError();
-    EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value";
-    consumeError(std::move(E));
-  }
+// Test Expected<T> in failure mode.
+TEST(Error, ExpectedInFailureMode) {
+  Expected<int> A = make_error<CustomError>(42);
+  EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'";
+  Error E = A.takeError();
+  EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value";
+  consumeError(std::move(E));
+}
 
 // Check that an Expected instance with an error value doesn't allow access to
 // operator*.
 // Test runs in debug mode only.
 #ifndef NDEBUG
-  {
-    Expected<int> A = make_error<CustomError>(42);
-    EXPECT_DEATH(*A, "!HasError && \"Cannot get value when an error exists!\"")
-        << "Incorrect Expected error value";
-    consumeError(A.takeError());
-  }
+TEST(Error, AccessExpectedInFailureMode) {
+  Expected<int> A = make_error<CustomError>(42);
+  EXPECT_DEATH(*A, "!HasError && \"Cannot get value when an error exists!\"")
+      << "Incorrect Expected error value";
+  consumeError(A.takeError());
+}
 #endif
 
 // Check that an Expected instance with an error triggers an abort if
 // unhandled.
 // Test runs in debug mode only.
 #ifndef NDEBUG
+TEST(Error, UnhandledExpectedInFailureMode) {
   EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); },
                "Program aborted due to an unhandled Error:")
       << "Unchecked Expected<T> failure value did not cause an abort()";
+}
 #endif
 
-  // Test covariance of Expected.
-  {
-    class B {};
-    class D : public B {};
+// Test covariance of Expected.
+TEST(Error, ExpectedCovariance) {
+  class B {};
+  class D : public B {};
 
-    Expected<B *> A1(Expected<D *>(nullptr));
-    A1 = Expected<D *>(nullptr);
+  Expected<B *> A1(Expected<D *>(nullptr));
+  A1 = Expected<D *>(nullptr);
 
-    Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr));
-    A2 = Expected<std::unique_ptr<D>>(nullptr);
-  }
+  Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr));
+  A2 = Expected<std::unique_ptr<D>>(nullptr);
 }
 
 TEST(Error, ECError) {
-
   // Round-trip a success value to check that it converts correctly.
   EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())),
             std::error_code())




More information about the llvm-commits mailing list