Skip to content

Commit

Permalink
[gtest] Create a shared include directory for gtest utilities.
Browse files Browse the repository at this point in the history
Many times unit tests for different libraries would like to use
the same helper functions for checking common types of errors.

This patch adds a common library with helpers for testing things
in Support, and introduces helpers in here for integrating the
llvm::Error and llvm::Expected<T> classes with gtest and gmock.

Normally, we would just be able to write:

   EXPECT_THAT(someFunction(), succeeded());

but due to some quirks in llvm::Error's move semantics, gmock
doesn't make this easy, so two macros EXPECT_THAT_ERROR() and
EXPECT_THAT_EXPECTED() are introduced to gloss over the difficulties.
Consider this an exception, and possibly only temporary as we
look for ways to improve this.

Differential Revision: https://reviews.llvm.org/D33059

llvm-svn: 305395
  • Loading branch information
Zachary Turner committed Jun 14, 2017
1 parent b6567b1 commit cb30e70
Show file tree
Hide file tree
Showing 22 changed files with 441 additions and 373 deletions.
69 changes: 69 additions & 0 deletions llvm/include/llvm/Testing/Support/Error.h
@@ -0,0 +1,69 @@
//===- llvm/Testing/Support/Error.h ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TESTING_SUPPORT_ERROR_H
#define LLVM_TESTING_SUPPORT_ERROR_H

#include "llvm/ADT/Optional.h"
#include "llvm/Support/Error.h"
#include "llvm/Testing/Support/SupportHelpers.h"

#include "gmock/gmock.h"
#include <ostream>

namespace llvm {
namespace detail {
ErrorHolder TakeError(Error Err);

template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &Exp) {
llvm::detail::ExpectedHolder<T> Result;
auto &EH = static_cast<llvm::detail::ErrorHolder &>(Result);
EH = TakeError(Exp.takeError());
if (Result.Success)
Result.Value = &(*Exp);
return Result;
}

template <typename T> ExpectedHolder<T> TakeExpected(const Expected<T> &Exp) {
return TakeExpected(const_cast<Expected<T> &>(Exp));
}
} // namespace detail

#define EXPECT_THAT_ERROR(Err, Matcher) \
EXPECT_THAT(llvm::detail::TakeError(Err), Matcher)
#define ASSERT_THAT_ERROR(Err, Matcher) \
ASSERT_THAT(llvm::detail::TakeError(Err), Matcher)

#define EXPECT_THAT_EXPECTED(Err, Matcher) \
EXPECT_THAT(llvm::detail::TakeExpected(Err), Matcher)
#define ASSERT_THAT_EXPECTED(Err, Matcher) \
ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher)

MATCHER(Succeeded, "") { return arg.Success; }
MATCHER(Failed, "") { return !arg.Success; }

MATCHER_P(HasValue, value,
"succeeded with value " + testing::PrintToString(value)) {
if (!arg.Success) {
*result_listener << "operation failed";
return false;
}

assert(arg.Value.hasValue());
if (**arg.Value != value) {
*result_listener << "but \"" + testing::PrintToString(**arg.Value) +
"\" != " + testing::PrintToString(value);
return false;
}

return true;
}
} // namespace llvm

#endif
46 changes: 46 additions & 0 deletions llvm/include/llvm/Testing/Support/SupportHelpers.h
@@ -0,0 +1,46 @@
//===- Testing/Support/SupportHelpers.h -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H
#define LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"

namespace llvm {
namespace detail {
struct ErrorHolder {
bool Success;
std::string Message;
};

template <typename T> struct ExpectedHolder : public ErrorHolder {
Optional<T *> Value;
};

inline void PrintTo(const ErrorHolder &Err, std::ostream *Out) {
*Out << (Err.Success ? "succeeded" : "failed");
if (!Err.Success) {
*Out << " (" << StringRef(Err.Message).trim().str() << ")";
}
}

template <typename T>
void PrintTo(const ExpectedHolder<T> &Item, std::ostream *Out) {
if (Item.Success) {
*Out << "succeeded with value \"" << testing::PrintToString(**Item.Value)
<< "\"";
} else {
PrintTo(static_cast<const ErrorHolder &>(Item), Out);
}
}
} // namespace detail
} // namespace llvm

#endif
1 change: 1 addition & 0 deletions llvm/lib/CMakeLists.txt
Expand Up @@ -24,3 +24,4 @@ add_subdirectory(Fuzzer)
add_subdirectory(Passes)
add_subdirectory(ToolDrivers)
add_subdirectory(XRay)
add_subdirectory(Testing)
1 change: 1 addition & 0 deletions llvm/lib/LLVMBuild.txt
Expand Up @@ -39,6 +39,7 @@ subdirectories =
Support
TableGen
Target
Testing
ToolDrivers
Transforms

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Testing/CMakeLists.txt
@@ -0,0 +1 @@
add_subdirectory(Support)
19 changes: 19 additions & 0 deletions llvm/lib/Testing/LLVMBuild.txt
@@ -0,0 +1,19 @@
;===- ./lib/Testing/LLVMBuild.txt ------------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[common]
subdirectories = Support
12 changes: 12 additions & 0 deletions llvm/lib/Testing/Support/CMakeLists.txt
@@ -0,0 +1,12 @@
add_llvm_library(LLVMTestingSupport
Error.cpp

BUILDTREE_ONLY

ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Testing/Support
)

include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include)
include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock/include)
target_link_libraries(LLVMTestingSupport PRIVATE gtest)
22 changes: 22 additions & 0 deletions llvm/lib/Testing/Support/Error.cpp
@@ -0,0 +1,22 @@
//===- llvm/Testing/Support/Error.cpp -------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Testing/Support/Error.h"

#include "llvm/ADT/StringRef.h"

using namespace llvm;

llvm::detail::ErrorHolder llvm::detail::TakeError(llvm::Error Err) {
bool Succeeded = !static_cast<bool>(Err);
std::string Message;
if (!Succeeded)
Message = toString(std::move(Err));
return {Succeeded, Message};
}
22 changes: 22 additions & 0 deletions llvm/lib/Testing/Support/LLVMBuild.txt
@@ -0,0 +1,22 @@
;===- ./Testing/Support/LLVMBuild.txt --------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[component_0]
type = Library
name = TestingSupport
parent = Libraries
required_libraries = Support
25 changes: 13 additions & 12 deletions llvm/unittests/DebugInfo/CodeView/CMakeLists.txt
@@ -1,12 +1,13 @@
set(LLVM_LINK_COMPONENTS
DebugInfoCodeView
)

set(DebugInfoCodeViewSources
RandomAccessVisitorTest.cpp
TypeIndexDiscoveryTest.cpp
)

add_llvm_unittest(DebugInfoCodeViewTests
${DebugInfoCodeViewSources}
)
set(LLVM_LINK_COMPONENTS
DebugInfoCodeView
TestingSupport
)

set(DebugInfoCodeViewSources
RandomAccessVisitorTest.cpp
TypeIndexDiscoveryTest.cpp
)

add_llvm_unittest(DebugInfoCodeViewTests
${DebugInfoCodeViewSources}
)
70 changes: 0 additions & 70 deletions llvm/unittests/DebugInfo/CodeView/ErrorChecking.h

This file was deleted.

18 changes: 11 additions & 7 deletions llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp
Expand Up @@ -7,8 +7,6 @@
//
//===----------------------------------------------------------------------===//

#include "ErrorChecking.h"

#include "llvm/ADT/SmallBitVector.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
Expand All @@ -22,6 +20,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryItemStream.h"
#include "llvm/Support/Error.h"
#include "llvm/Testing/Support/Error.h"

#include "gtest/gtest.h"

Expand Down Expand Up @@ -219,7 +218,8 @@ TEST_F(RandomAccessVisitorTest, MultipleVisits) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
Succeeded());
}

// [0,8) should be present
Expand Down Expand Up @@ -247,7 +247,8 @@ TEST_F(RandomAccessVisitorTest, DescendingWithinChunk) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
Succeeded());
}

// [0, 7]
Expand Down Expand Up @@ -275,7 +276,8 @@ TEST_F(RandomAccessVisitorTest, AscendingWithinChunk) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
Succeeded());
}

// [0, 7]
Expand Down Expand Up @@ -305,7 +307,8 @@ TEST_F(RandomAccessVisitorTest, StopPrematurelyInChunk) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
Succeeded());
}

// [0, 8) should be visited.
Expand Down Expand Up @@ -334,7 +337,8 @@ TEST_F(RandomAccessVisitorTest, InnerChunk) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
Succeeded());
}

// [4, 9)
Expand Down
Expand Up @@ -9,7 +9,6 @@

#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"

#include "ErrorChecking.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/Support/Allocator.h"

Expand Down
1 change: 1 addition & 0 deletions llvm/unittests/DebugInfo/PDB/CMakeLists.txt
Expand Up @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS
DebugInfoCodeView
DebugInfoMSF
DebugInfoPDB
TestingSupport
)

set(DebugInfoPDBSources
Expand Down

0 comments on commit cb30e70

Please sign in to comment.