llvm/llvm/unittests/Support/ErrorTest.cpp

//===----- unittests/ErrorTest.cpp - Error.h tests ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Error.h"
#include "llvm-c/Error.h"

#include "llvm/ADT/Twine.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
#include "gtest/gtest-spi.h"
#include "gtest/gtest.h"
#include <memory>

usingnamespacellvm;

namespace {

// Custom error class with a default base class and some random 'info' attached.
class CustomError : public ErrorInfo<CustomError> {};

char CustomError::ID =;

// Custom error class with a custom base class and some additional random
// 'info'.
class CustomSubError : public ErrorInfo<CustomSubError, CustomError> {};

char CustomSubError::ID =;

static Error handleCustomError(const CustomError &CE) {}

static void handleCustomErrorVoid(const CustomError &CE) {}

static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) {}

static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {}

// Test that success values implicitly convert to false, and don't cause crashes
// once they've been implicitly converted.
TEST(Error, CheckedSuccess) {}

// Test that unchecked success values cause an abort.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, UncheckedSuccess) {
  EXPECT_DEATH({ Error E = Error::success(); },
               "Program aborted due to an unhandled Error:")
      << "Unchecked Error Succes value did not cause abort()";
}
#endif

// ErrorAsOutParameter tester.
void errAsOutParamHelper(Error &Err) {}

// Test that ErrorAsOutParameter sets the checked flag on construction.
TEST(Error, ErrorAsOutParameterChecked) {}

// Test that ErrorAsOutParameter clears the checked flag on destruction.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, ErrorAsOutParameterUnchecked) {
  EXPECT_DEATH({ Error E = Error::success(); errAsOutParamHelper(E); },
               "Program aborted due to an unhandled Error:")
      << "ErrorAsOutParameter did not clear the checked flag on destruction.";
}
#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.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
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 that we can handle a custom error.
TEST(Error, HandleCustomError) {}

// 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) {}

// Test that we can handle errors with custom base classes.
TEST(Error, HandleCustomErrorWithCustomBaseClass) {}

// Check that we trigger only the first handler that applies.
TEST(Error, FirstHandlerOnly) {}

// Check that general handlers shadow specific ones.
TEST(Error, HandlerShadowing) {}

// Test joinErrors.
TEST(Error, CheckJoinErrors) {}

// Test that we can consume success values.
TEST(Error, ConsumeSuccess) {}

TEST(Error, ConsumeError) {}

// Test that handleAllUnhandledErrors crashes if an error is not caught.
// Test runs in debug mode only.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, FailureToHandle) {
  auto FailToHandle = []() {
    handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) {
      errs() << "This should never be called";
      exit(1);
    });
  };

  EXPECT_DEATH(FailToHandle(),
               "Failure value returned from cantFail wrapped call\n"
               "CustomError \\{7\\}")
      << "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.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, FailureFromHandler) {
  auto ReturnErrorFromHandler = []() {
    handleAllErrors(make_error<CustomError>(7),
                    [&](std::unique_ptr<CustomSubError> SE) {
                      return Error(std::move(SE));
                    });
  };

  EXPECT_DEATH(ReturnErrorFromHandler(),
               "Failure value returned from cantFail wrapped call\n"
               "CustomError \\{7\\}")
      << " Error returned from handler in handleAllErrors call did not "
         "cause abort()";
}
#endif

// Test that we can return values from handleErrors.
TEST(Error, CatchErrorFromHandler) {}

TEST(Error, StringError) {}

TEST(Error, createStringError) {}

// Test that the ExitOnError utility works as expected.
TEST(ErrorDeathTest, ExitOnError) {}

// Test that the ExitOnError utility works as expected.
TEST(Error, CantFailSuccess) {}

// Test that cantFail results in a crash if you pass it a failure value.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
TEST(Error, CantFailDeath) {
  EXPECT_DEATH(cantFail(make_error<StringError>("Original error message",
                                                inconvertibleErrorCode()),
                        "Cantfail call failed"),
               "Cantfail call failed\n"
               "Original error message")
      << "cantFail(Error) did not cause an abort for failure value";

  EXPECT_DEATH(
      {
        auto IEC = inconvertibleErrorCode();
        int X = cantFail(Expected<int>(make_error<StringError>("foo", IEC)));
        (void)X;
      },
      "Failure value returned from cantFail wrapped call")
    << "cantFail(Expected<int>) did not cause an abort for failure value";
}
#endif


// Test Checked Expected<T> in success mode.
TEST(Error, CheckedExpectedInSuccessMode) {}

// Test Expected with reference type.
TEST(Error, ExpectedWithReferenceType) {}

// Test Unchecked Expected<T> in success mode.
// We expect this to blow up the same way Error would.
// Test runs in debug mode only.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, UncheckedExpectedInSuccessModeDestruction) {
  EXPECT_DEATH({ Expected<int> A = 7; },
               "Expected<T> must be checked before access or destruction.")
      << "Unchecked Expected<T> success value did not cause an abort().";
}
#endif

// Test Unchecked Expected<T> in success mode.
// We expect this to blow up the same way Error would.
// Test runs in debug mode only.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, UncheckedExpectedInSuccessModeAccess) {
  EXPECT_DEATH(
      {
        const Expected<int> A = 7;
        *A;
      },
      "Expected<T> must be checked before access or destruction.")
      << "Unchecked Expected<T> success value did not cause an abort().";
}
#endif

// Test Unchecked Expected<T> in success mode.
// We expect this to blow up the same way Error would.
// Test runs in debug mode only.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, UncheckedExpectedInSuccessModeAssignment) {
  EXPECT_DEATH(
      {
        Expected<int> A = 7;
        A = 7;
      },
      "Expected<T> must be checked before access or destruction.")
      << "Unchecked Expected<T> success value did not cause an abort().";
}
#endif

// Test Expected<T> in failure mode.
TEST(Error, ExpectedInFailureMode) {}

// Check that an Expected instance with an error value doesn't allow access to
// operator*.
// Test runs in debug mode only.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, AccessExpectedInFailureMode) {
  Expected<int> A = make_error<CustomError>(42);
  EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.")
      << "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.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
TEST(Error, UnhandledExpectedInFailureMode) {
  EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); },
               "Expected<T> must be checked before access or destruction.")
      << "Unchecked Expected<T> failure value did not cause an abort()";
}
#endif

// Test covariance of Expected.
TEST(Error, ExpectedCovariance) {}

// Test that handleExpected just returns success values.
TEST(Error, HandleExpectedSuccess) {}

enum FooStrategy {};

static Expected<int> foo(FooStrategy S) {}

// Test that handleExpected invokes the error path if errors are not handled.
TEST(Error, HandleExpectedUnhandledError) {}

// Test that handleExpected invokes the fallback path if errors are handled.
TEST(Error, HandleExpectedHandledError) {}

TEST(Error, ErrorCodeConversions) {}

// Test that error messages work.
TEST(Error, ErrorMessage) {}

TEST(Error, Stream) {}

TEST(Error, SucceededMatcher) {}

TEST(Error, FailedMatcher) {}

TEST(Error, HasValueMatcher) {}

TEST(Error, FailedWithMessageMatcher) {}

TEST(Error, C_API) {}

TEST(Error, FileErrorTest) {}

TEST(Error, FileErrorErrorCode) {}

enum class test_error_code {};

} // end anon namespace

namespace std {
    template <>
    struct is_error_code_enum<test_error_code> : std::true_type {};
} // namespace std

namespace {

const std::error_category &TErrorCategory();

inline std::error_code make_error_code(test_error_code E) {}

class TestDebugError : public ErrorInfo<TestDebugError, StringError> {};

class TestErrorCategory : public std::error_category {};

const std::error_category &TErrorCategory() {}

char TestDebugError::ID;

TEST(Error, SubtypeStringErrorTest) {}

static Error createAnyError() {}

struct MoveOnlyBox {};

TEST(Error, moveInto) {}

TEST(Error, FatalBadAllocErrorHandlersInteraction) {}

TEST(Error, BadAllocFatalErrorHandlersInteraction) {}

TEST(Error, ForwardToExpected) {}
} // namespace