diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
commit | 01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch) | |
tree | 4def12e759965de927d963ac65840d663ef9d1ea /unittests/Support | |
parent | f0f4822ed4b66e3579e92a89f368f8fb860e218e (diff) |
Diffstat (limited to 'unittests/Support')
22 files changed, 1645 insertions, 155 deletions
diff --git a/unittests/Support/AlignOfTest.cpp b/unittests/Support/AlignOfTest.cpp index be208f7d28ea8..74b03f0e7dfd3 100644 --- a/unittests/Support/AlignOfTest.cpp +++ b/unittests/Support/AlignOfTest.cpp @@ -1,4 +1,4 @@ -//=== - llvm/unittest/Support/AlignOfTest.cpp - Alignment utility tests ----===// +//=== - llvm/unittest/Support/AlignOfTest.cpp - Alignment utility tests ---===// // // The LLVM Compiler Infrastructure // @@ -97,7 +97,7 @@ struct Abstract1 { }; struct Abstract2 : Abstract1 { - virtual ~Abstract2() {} + ~Abstract2() override = default; double d; }; @@ -354,4 +354,4 @@ TEST(AlignOfTest, BasicAlignedArray) { EXPECT_EQ(2u, sizeof(AlignedCharArray<2, 2>)); EXPECT_EQ(16u, sizeof(AlignedCharArray<2, 16>)); } -} +} // end anonymous namespace diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 3ab98d58d5f0d..9a4a144509115 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} Support ) @@ -17,6 +16,7 @@ add_llvm_unittest(SupportTests DwarfTest.cpp EndianStreamTest.cpp EndianTest.cpp + ErrorTest.cpp ErrorOrTest.cpp FileOutputBufferTest.cpp IteratorTest.cpp @@ -36,14 +36,15 @@ add_llvm_unittest(SupportTests ScaledNumberTest.cpp SourceMgrTest.cpp SpecialCaseListTest.cpp - StreamingMemoryObject.cpp + StreamingMemoryObjectTest.cpp StringPool.cpp SwapByteOrderTest.cpp - TargetRegistry.cpp + TargetParserTest.cpp ThreadLocalTest.cpp ThreadPool.cpp TimerTest.cpp TimeValueTest.cpp + TypeNameTest.cpp TrailingObjectsTest.cpp UnicodeTest.cpp YAMLIOTest.cpp @@ -51,9 +52,8 @@ add_llvm_unittest(SupportTests formatted_raw_ostream_test.cpp raw_ostream_test.cpp raw_pwrite_stream_test.cpp + raw_sha1_ostream_test.cpp ) # ManagedStatic.cpp uses <pthread>. -if(LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD) - target_link_libraries(SupportTests pthread) -endif() +target_link_libraries(SupportTests ${PTHREAD_LIB}) diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index eac669f467b7d..9b24c1e40bcad 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -67,6 +67,22 @@ public: : Base(M0, M1, M2, M3) {} ~StackOption() override { this->removeArgument(); } + + template <class DT> StackOption<T> &operator=(const DT &V) { + this->setValue(V); + return *this; + } +}; + +class StackSubCommand : public cl::SubCommand { +public: + StackSubCommand(const char *const Name, + const char *const Description = nullptr) + : SubCommand(Name, Description) {} + + StackSubCommand() : SubCommand() {} + + ~StackSubCommand() { unregisterSubCommand(); } }; @@ -78,7 +94,8 @@ TEST(CommandLineTest, ModifyExisitingOption) { const char ArgString[] = "new-test-option"; const char ValueString[] = "Integer"; - StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); + StringMap<cl::Option *> &Map = + cl::getRegisteredOptions(*cl::TopLevelSubCommand); ASSERT_TRUE(Map.count("test-option") == 1) << "Could not find option in map."; @@ -165,11 +182,12 @@ void testCommandLineTokenizer(ParserFunction *parse, const char *Input, } TEST(CommandLineTest, TokenizeGNUCommandLine) { - const char *Input = "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' " - "foo\"bar\"baz C:\\src\\foo.cpp \"C:\\src\\foo.cpp\""; - const char *const Output[] = { "foo bar", "foo bar", "foo bar", "foo\\bar", - "foobarbaz", "C:\\src\\foo.cpp", - "C:\\src\\foo.cpp" }; + const char *Input = + "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' -DFOO=bar\\(\\) " + "foo\"bar\"baz C:\\\\src\\\\foo.cpp \"C:\\src\\foo.cpp\""; + const char *const Output[] = { + "foo bar", "foo bar", "foo bar", "foo\\bar", + "-DFOO=bar()", "foobarbaz", "C:\\src\\foo.cpp", "C:srcfoo.cpp"}; testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output, array_lengthof(Output)); } @@ -236,7 +254,8 @@ TEST(CommandLineTest, HideUnrelatedOptions) { ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag()) << "Hid extra option that should be visable."; - StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); + StringMap<cl::Option *> &Map = + cl::getRegisteredOptions(*cl::TopLevelSubCommand); ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag()) << "Hid default option that should be visable."; } @@ -260,9 +279,201 @@ TEST(CommandLineTest, HideUnrelatedOptionsMulti) { ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag()) << "Hid extra option that should be visable."; - StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); + StringMap<cl::Option *> &Map = + cl::getRegisteredOptions(*cl::TopLevelSubCommand); ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag()) << "Hid default option that should be visable."; } +TEST(CommandLineTest, SetValueInSubcategories) { + cl::ResetCommandLineParser(); + + StackSubCommand SC1("sc1", "First subcommand"); + StackSubCommand SC2("sc2", "Second subcommand"); + + StackOption<bool> TopLevelOpt("top-level", cl::init(false)); + StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false)); + StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false)); + + EXPECT_FALSE(TopLevelOpt); + EXPECT_FALSE(SC1Opt); + EXPECT_FALSE(SC2Opt); + const char *args[] = {"prog", "-top-level"}; + EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true)); + EXPECT_TRUE(TopLevelOpt); + EXPECT_FALSE(SC1Opt); + EXPECT_FALSE(SC2Opt); + + TopLevelOpt = false; + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(TopLevelOpt); + EXPECT_FALSE(SC1Opt); + EXPECT_FALSE(SC2Opt); + const char *args2[] = {"prog", "sc1", "-sc1"}; + EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true)); + EXPECT_FALSE(TopLevelOpt); + EXPECT_TRUE(SC1Opt); + EXPECT_FALSE(SC2Opt); + + SC1Opt = false; + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(TopLevelOpt); + EXPECT_FALSE(SC1Opt); + EXPECT_FALSE(SC2Opt); + const char *args3[] = {"prog", "sc2", "-sc2"}; + EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, nullptr, true)); + EXPECT_FALSE(TopLevelOpt); + EXPECT_FALSE(SC1Opt); + EXPECT_TRUE(SC2Opt); +} + +TEST(CommandLineTest, LookupFailsInWrongSubCommand) { + cl::ResetCommandLineParser(); + + StackSubCommand SC1("sc1", "First subcommand"); + StackSubCommand SC2("sc2", "Second subcommand"); + + StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false)); + StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false)); + + const char *args[] = {"prog", "sc1", "-sc2"}; + EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, nullptr, true)); +} + +TEST(CommandLineTest, AddToAllSubCommands) { + cl::ResetCommandLineParser(); + + StackSubCommand SC1("sc1", "First subcommand"); + StackOption<bool> AllOpt("everywhere", cl::sub(*cl::AllSubCommands), + cl::init(false)); + StackSubCommand SC2("sc2", "Second subcommand"); + + const char *args[] = {"prog", "-everywhere"}; + const char *args2[] = {"prog", "sc1", "-everywhere"}; + const char *args3[] = {"prog", "sc2", "-everywhere"}; + + EXPECT_FALSE(AllOpt); + EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true)); + EXPECT_TRUE(AllOpt); + + AllOpt = false; + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(AllOpt); + EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true)); + EXPECT_TRUE(AllOpt); + + AllOpt = false; + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(AllOpt); + EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, nullptr, true)); + EXPECT_TRUE(AllOpt); +} + +TEST(CommandLineTest, ReparseCommandLineOptions) { + cl::ResetCommandLineParser(); + + StackOption<bool> TopLevelOpt("top-level", cl::sub(*cl::TopLevelSubCommand), + cl::init(false)); + + const char *args[] = {"prog", "-top-level"}; + + EXPECT_FALSE(TopLevelOpt); + EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true)); + EXPECT_TRUE(TopLevelOpt); + + TopLevelOpt = false; + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(TopLevelOpt); + EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true)); + EXPECT_TRUE(TopLevelOpt); +} + +TEST(CommandLineTest, RemoveFromRegularSubCommand) { + cl::ResetCommandLineParser(); + + StackSubCommand SC("sc", "Subcommand"); + StackOption<bool> RemoveOption("remove-option", cl::sub(SC), cl::init(false)); + StackOption<bool> KeepOption("keep-option", cl::sub(SC), cl::init(false)); + + const char *args[] = {"prog", "sc", "-remove-option"}; + + EXPECT_FALSE(RemoveOption); + EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, nullptr, true)); + EXPECT_TRUE(RemoveOption); + + RemoveOption.removeArgument(); + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, nullptr, true)); +} + +TEST(CommandLineTest, RemoveFromTopLevelSubCommand) { + cl::ResetCommandLineParser(); + + StackOption<bool> TopLevelRemove( + "top-level-remove", cl::sub(*cl::TopLevelSubCommand), cl::init(false)); + StackOption<bool> TopLevelKeep( + "top-level-keep", cl::sub(*cl::TopLevelSubCommand), cl::init(false)); + + const char *args[] = {"prog", "-top-level-remove"}; + + EXPECT_FALSE(TopLevelRemove); + EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true)); + EXPECT_TRUE(TopLevelRemove); + + TopLevelRemove.removeArgument(); + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, nullptr, true)); +} + +TEST(CommandLineTest, RemoveFromAllSubCommands) { + cl::ResetCommandLineParser(); + + StackSubCommand SC1("sc1", "First Subcommand"); + StackSubCommand SC2("sc2", "Second Subcommand"); + StackOption<bool> RemoveOption("remove-option", cl::sub(*cl::AllSubCommands), + cl::init(false)); + StackOption<bool> KeepOption("keep-option", cl::sub(*cl::AllSubCommands), + cl::init(false)); + + const char *args0[] = {"prog", "-remove-option"}; + const char *args1[] = {"prog", "sc1", "-remove-option"}; + const char *args2[] = {"prog", "sc2", "-remove-option"}; + + // It should work for all subcommands including the top-level. + EXPECT_FALSE(RemoveOption); + EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, nullptr, true)); + EXPECT_TRUE(RemoveOption); + + RemoveOption = false; + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(RemoveOption); + EXPECT_TRUE(cl::ParseCommandLineOptions(3, args1, nullptr, true)); + EXPECT_TRUE(RemoveOption); + + RemoveOption = false; + + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(RemoveOption); + EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true)); + EXPECT_TRUE(RemoveOption); + + RemoveOption.removeArgument(); + + // It should not work for any subcommands including the top-level. + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(cl::ParseCommandLineOptions(2, args0, nullptr, true)); + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(cl::ParseCommandLineOptions(3, args1, nullptr, true)); + cl::ResetAllOptionOccurrences(); + EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, nullptr, true)); +} + } // anonymous namespace diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index d436fc0228963..0af09e98a2178 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ConvertUTF.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Format.h" #include "gtest/gtest.h" #include <string> @@ -59,7 +60,7 @@ TEST(ConvertUTFTest, OddLengthInput) { TEST(ConvertUTFTest, Empty) { std::string Result; - bool Success = convertUTF16ToUTF8String(None, Result); + bool Success = convertUTF16ToUTF8String(llvm::ArrayRef<char>(None), Result); EXPECT_TRUE(Success); EXPECT_TRUE(Result.empty()); } @@ -80,6 +81,41 @@ TEST(ConvertUTFTest, HasUTF16BOM) { EXPECT_FALSE(HasBOM); } +TEST(ConvertUTFTest, UTF16WrappersForConvertUTF16ToUTF8String) { + // Src is the look of disapproval. + static const char Src[] = "\xff\xfe\xa0\x0c_\x00\xa0\x0c"; + ArrayRef<UTF16> SrcRef = makeArrayRef((const UTF16 *)Src, 4); + std::string Result; + bool Success = convertUTF16ToUTF8String(SrcRef, Result); + EXPECT_TRUE(Success); + std::string Expected("\xe0\xb2\xa0_\xe0\xb2\xa0"); + EXPECT_EQ(Expected, Result); +} + +TEST(ConvertUTFTest, ConvertUTF8toWide) { + // Src is the look of disapproval. + static const char Src[] = "\xe0\xb2\xa0_\xe0\xb2\xa0"; + std::wstring Result; + bool Success = ConvertUTF8toWide((const char*)Src, Result); + EXPECT_TRUE(Success); + std::wstring Expected(L"\x0ca0_\x0ca0"); + EXPECT_EQ(Expected, Result); + Result.clear(); + Success = ConvertUTF8toWide(StringRef(Src, 7), Result); + EXPECT_TRUE(Success); + EXPECT_EQ(Expected, Result); +} + +TEST(ConvertUTFTest, convertWideToUTF8) { + // Src is the look of disapproval. + static const wchar_t Src[] = L"\x0ca0_\x0ca0"; + std::string Result; + bool Success = convertWideToUTF8(Src, Result); + EXPECT_TRUE(Success); + std::string Expected("\xe0\xb2\xa0_\xe0\xb2\xa0"); + EXPECT_EQ(Expected, Result); +} + struct ConvertUTFResultContainer { ConversionResult ErrorCode; std::vector<unsigned> UnicodeScalars; diff --git a/unittests/Support/EndianStreamTest.cpp b/unittests/Support/EndianStreamTest.cpp index 6a69be55f9266..ea6c308c560a7 100644 --- a/unittests/Support/EndianStreamTest.cpp +++ b/unittests/Support/EndianStreamTest.cpp @@ -153,5 +153,56 @@ TEST(EndianStream, WriteDoubleBE) { EXPECT_EQ(static_cast<uint8_t>(data[7]), 0x20); } +TEST(EndianStream, WriteArrayLE) { + SmallString<16> Data; + + { + raw_svector_ostream OS(Data); + endian::Writer<little> LE(OS); + LE.write<uint16_t>({0x1234, 0x5678}); + } + + EXPECT_EQ(static_cast<uint8_t>(Data[0]), 0x34); + EXPECT_EQ(static_cast<uint8_t>(Data[1]), 0x12); + EXPECT_EQ(static_cast<uint8_t>(Data[2]), 0x78); + EXPECT_EQ(static_cast<uint8_t>(Data[3]), 0x56); +} + +TEST(EndianStream, WriteVectorLE) { + SmallString<16> Data; + + { + raw_svector_ostream OS(Data); + endian::Writer<little> LE(OS); + std::vector<uint16_t> Vec{0x1234, 0x5678}; + LE.write<uint16_t>(Vec); + } + + EXPECT_EQ(static_cast<uint8_t>(Data[0]), 0x34); + EXPECT_EQ(static_cast<uint8_t>(Data[1]), 0x12); + EXPECT_EQ(static_cast<uint8_t>(Data[2]), 0x78); + EXPECT_EQ(static_cast<uint8_t>(Data[3]), 0x56); +} + +TEST(EndianStream, WriteFloatArrayLE) { + SmallString<16> Data; + + { + raw_svector_ostream OS(Data); + endian::Writer<little> LE(OS); + LE.write<float>({12345.0f, 12346.0f}); + } + + EXPECT_EQ(static_cast<uint8_t>(Data[0]), 0x00); + EXPECT_EQ(static_cast<uint8_t>(Data[1]), 0xE4); + EXPECT_EQ(static_cast<uint8_t>(Data[2]), 0x40); + EXPECT_EQ(static_cast<uint8_t>(Data[3]), 0x46); + + EXPECT_EQ(static_cast<uint8_t>(Data[4]), 0x00); + EXPECT_EQ(static_cast<uint8_t>(Data[5]), 0xE8); + EXPECT_EQ(static_cast<uint8_t>(Data[6]), 0x40); + EXPECT_EQ(static_cast<uint8_t>(Data[7]), 0x46); +} + } // end anon namespace diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index 73d0e3f2bb711..87dcab7b181ec 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -16,7 +16,7 @@ using namespace llvm; namespace { -ErrorOr<int> t1() {return 1;} +ErrorOr<int> t1() { return 1; } ErrorOr<int> t2() { return errc::invalid_argument; } TEST(ErrorOr, SimpleValue) { @@ -71,6 +71,46 @@ TEST(ErrorOr, Comparison) { EXPECT_EQ(x, errc::no_such_file_or_directory); } +TEST(ErrorOr, ImplicitConversion) { + ErrorOr<std::string> x("string literal"); + EXPECT_TRUE(!!x); +} + +TEST(ErrorOr, ImplicitConversionCausesMove) { + struct Source {}; + struct Destination { + Destination(const Source&) {} + Destination(Source&&) = delete; + }; + Source s; + ErrorOr<Destination> x = s; + EXPECT_TRUE(!!x); +} + +TEST(ErrorOr, ImplicitConversionNoAmbiguity) { + struct CastsToErrorCode { + CastsToErrorCode() = default; + CastsToErrorCode(std::error_code) {} + operator std::error_code() { return errc::invalid_argument; } + } casts_to_error_code; + ErrorOr<CastsToErrorCode> x1(casts_to_error_code); + ErrorOr<CastsToErrorCode> x2 = casts_to_error_code; + ErrorOr<CastsToErrorCode> x3 = {casts_to_error_code}; + ErrorOr<CastsToErrorCode> x4{casts_to_error_code}; + ErrorOr<CastsToErrorCode> x5(errc::no_such_file_or_directory); + ErrorOr<CastsToErrorCode> x6 = errc::no_such_file_or_directory; + ErrorOr<CastsToErrorCode> x7 = {errc::no_such_file_or_directory}; + ErrorOr<CastsToErrorCode> x8{errc::no_such_file_or_directory}; + EXPECT_TRUE(!!x1); + EXPECT_TRUE(!!x2); + EXPECT_TRUE(!!x3); + EXPECT_TRUE(!!x4); + EXPECT_FALSE(x5); + EXPECT_FALSE(x6); + EXPECT_FALSE(x7); + EXPECT_FALSE(x8); +} + // ErrorOr<int*> x(nullptr); // ErrorOr<std::unique_ptr<int>> y = x; // invalid conversion static_assert( diff --git a/unittests/Support/ErrorTest.cpp b/unittests/Support/ErrorTest.cpp new file mode 100644 index 0000000000000..2050926837440 --- /dev/null +++ b/unittests/Support/ErrorTest.cpp @@ -0,0 +1,627 @@ +//===----- unittests/ErrorTest.cpp - Error.h tests ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Error.h" + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/ErrorHandling.h" +#include "gtest/gtest.h" +#include <memory> + +using namespace llvm; + +namespace { + +// Custom error class with a default base class and some random 'info' attached. +class CustomError : public ErrorInfo<CustomError> { +public: + // Create an error with some info attached. + CustomError(int Info) : Info(Info) {} + + // Get the info attached to this error. + int getInfo() const { return Info; } + + // Log this error to a stream. + void log(raw_ostream &OS) const override { + OS << "CustomError { " << getInfo() << "}"; + } + + std::error_code convertToErrorCode() const override { + llvm_unreachable("CustomError doesn't support ECError conversion"); + } + + // Used by ErrorInfo::classID. + static char ID; + +protected: + // This error is subclassed below, but we can't use inheriting constructors + // yet, so we can't propagate the constructors through ErrorInfo. Instead + // we have to have a default constructor and have the subclass initialize all + // fields. + CustomError() : Info(0) {} + + int Info; +}; + +char CustomError::ID = 0; + +// Custom error class with a custom base class and some additional random +// 'info'. +class CustomSubError : public ErrorInfo<CustomSubError, CustomError> { +public: + // Create a sub-error with some info attached. + CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) { + this->Info = Info; + } + + // Get the extra info attached to this error. + int getExtraInfo() const { return ExtraInfo; } + + // Log this error to a stream. + void log(raw_ostream &OS) const override { + OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}"; + } + + std::error_code convertToErrorCode() const override { + llvm_unreachable("CustomSubError doesn't support ECError conversion"); + } + + // Used by ErrorInfo::classID. + static char ID; + +protected: + int ExtraInfo; +}; + +char CustomSubError::ID = 0; + +static Error handleCustomError(const CustomError &CE) { return Error(); } + +static void handleCustomErrorVoid(const CustomError &CE) {} + +static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { + return Error(); +} + +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) { + 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 + +// ErrorAsOutParameter tester. +void errAsOutParamHelper(Error &Err) { + ErrorAsOutParameter ErrAsOutParam(Err); + // Verify that checked flag is raised - assignment should not crash. + Err = Error::success(); + // Raise the checked bit manually - caller should still have to test the + // error. + (void)!!Err; +} + +// Test that ErrorAsOutParameter sets the checked flag on construction. +TEST(Error, ErrorAsOutParameterChecked) { + Error E; + errAsOutParamHelper(E); + (void)!!E; +} + +// Test that ErrorAsOutParameter clears the checked flag on destruction. +#ifndef NDEBUG +TEST(Error, ErrorAsOutParameterUnchecked) { + EXPECT_DEATH({ Error E; 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. +#ifndef NDEBUG +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)); +} + +// 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"; +} + +// 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) {}); + + handleAllErrors( + make_error<CustomError>(42), + [](const CustomError &CE) mutable { return Error::success(); }); + + handleAllErrors(make_error<CustomError>(42), + [](const CustomError &CE) mutable {}); + + handleAllErrors(make_error<CustomError>(42), + [](CustomError &CE) { return Error::success(); }); + + handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {}); + + handleAllErrors(make_error<CustomError>(42), + [](CustomError &CE) mutable { return Error::success(); }); + + handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {}); + + handleAllErrors( + make_error<CustomError>(42), + [](std::unique_ptr<CustomError> CE) { return Error::success(); }); + + handleAllErrors(make_error<CustomError>(42), + [](std::unique_ptr<CustomError> CE) {}); + + handleAllErrors( + make_error<CustomError>(42), + [](std::unique_ptr<CustomError> CE) mutable { return Error::success(); }); + + handleAllErrors(make_error<CustomError>(42), + [](std::unique_ptr<CustomError> CE) mutable {}); + + // Check that named handlers of type 'Error (const Err&)' work. + handleAllErrors(make_error<CustomError>(42), handleCustomError); + + // Check that named handlers of type 'void (const Err&)' work. + handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid); + + // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. + handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP); + + // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. + handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid); +} + +// 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"; +} + +// 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. +TEST(Error, HandlerShadowing) { + 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(); + }); + + EXPECT_TRUE(CaughtErrorInfo == 42 && DummyInfo == 0 && DummyExtraInfo == 0) + << "General Error handler did not shadow specific handler"; +} + +// 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."; + + // Test appending a single item to a list. + { + int Sum = 0; + handleAllErrors( + joinErrors( + joinErrors(make_error<CustomError>(7), + make_error<CustomError>(7)), + make_error<CustomError>(7)), + [&](const CustomError &CE) { + Sum += CE.getInfo(); + }); + EXPECT_EQ(Sum, 21) << "Failed to correctly append error to error list."; + } + + // Test prepending a single item to a list. + { + int Sum = 0; + handleAllErrors( + joinErrors( + make_error<CustomError>(7), + joinErrors(make_error<CustomError>(7), + make_error<CustomError>(7))), + [&](const CustomError &CE) { + Sum += CE.getInfo(); + }); + EXPECT_EQ(Sum, 21) << "Failed to correctly prepend error to error list."; + } + + // Test concatenating two error lists. + { + int Sum = 0; + handleAllErrors( + joinErrors( + joinErrors( + make_error<CustomError>(7), + make_error<CustomError>(7)), + joinErrors( + make_error<CustomError>(7), + make_error<CustomError>(7))), + [&](const CustomError &CE) { + Sum += CE.getInfo(); + }); + EXPECT_EQ(Sum, 28) << "Failed to correctly concatenate erorr lists."; + } +} + +// Test that we can consume success values. +TEST(Error, ConsumeSuccess) { + Error E; + 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 +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 +TEST(Error, FailureFromHandler) { + 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 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)); }); + + handleAllErrors(std::move(E), + [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); + + EXPECT_EQ(ErrorInfo, 7) + << "Failed to handle Error returned from handleErrors."; +} + +TEST(Error, StringError) { + std::string Msg; + raw_string_ostream S(Msg); + logAllUnhandledErrors(make_error<StringError>("foo" + Twine(42), + inconvertibleErrorCode()), + S, ""); + EXPECT_EQ(S.str(), "foo42\n") << "Unexpected StringError log result"; + + auto EC = + errorToErrorCode(make_error<StringError>("", errc::invalid_argument)); + EXPECT_EQ(EC, errc::invalid_argument) + << "Failed to convert StringError to error_code."; +} + +// 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"; + + int A = 7; + int &B = ExitOnErr(Expected<int&>(A)); + EXPECT_EQ(&A, &B) << "ExitOnError failed to propagate reference"; + + // 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:") + << "exitOnError returned an unexpected error result"; +} + +// Test Checked Expected<T> in success mode. +TEST(Error, CheckedExpectedInSuccessMode) { + Expected<int> A = 7; + EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'"; + // Access is safe in second test, since we checked the error in the first. + EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; +} + +// Test Expected with reference type. +TEST(Error, ExpectedWithReferenceType) { + int A = 7; + Expected<int&> B = A; + // 'Check' B. + (void)!!B; + int &C = *B; + EXPECT_EQ(&A, &C) << "Expected failed to propagate reference"; +} + +// Test Unchecked Expected<T> in success mode. +// We expect this to blow up the same way Error would. +// Test runs in debug mode only. +#ifndef NDEBUG +TEST(Error, UncheckedExpectedInSuccessModeDestruction) { + EXPECT_DEATH({ Expected<int> A = 7; }, + "Expected<T> must be checked before access or destruction.") + << "Unchecekd 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. +#ifndef NDEBUG +TEST(Error, UncheckedExpectedInSuccessModeAccess) { + EXPECT_DEATH({ Expected<int> A = 7; *A; }, + "Expected<T> must be checked before access or destruction.") + << "Unchecekd 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. +#ifndef NDEBUG +TEST(Error, UncheckedExpectedInSuccessModeAssignment) { + EXPECT_DEATH({ Expected<int> A = 7; A = 7; }, + "Expected<T> must be checked before access or destruction.") + << "Unchecekd Expected<T> success value did not cause an abort()."; +} +#endif + +// 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 +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. +#ifndef NDEBUG +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) { + class B {}; + class D : public B {}; + + Expected<B *> A1(Expected<D *>(nullptr)); + // Check A1 by converting to bool before assigning to it. + (void)!!A1; + A1 = Expected<D *>(nullptr); + // Check A1 again before destruction. + (void)!!A1; + + Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); + // Check A2 by converting to bool before assigning to it. + (void)!!A2; + A2 = Expected<std::unique_ptr<D>>(nullptr); + // Check A2 again before destruction. + (void)!!A2; +} + +TEST(Error, ErrorCodeConversions) { + // Round-trip a success value to check that it converts correctly. + EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), + std::error_code()) + << "std::error_code() should round-trip via Error conversions"; + + // Round-trip an error value to check that it converts correctly. + EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)), + errc::invalid_argument) + << "std::error_code error value should round-trip via Error " + "conversions"; + + // Round-trip a success value through ErrorOr/Expected to check that it + // converts correctly. + { + auto Orig = ErrorOr<int>(42); + auto RoundTripped = + expectedToErrorOr(errorOrToExpected(ErrorOr<int>(42))); + EXPECT_EQ(*Orig, *RoundTripped) + << "ErrorOr<T> success value should round-trip via Expected<T> " + "conversions."; + } + + // Round-trip a failure value through ErrorOr/Expected to check that it + // converts correctly. + { + auto Orig = ErrorOr<int>(errc::invalid_argument); + auto RoundTripped = + expectedToErrorOr( + errorOrToExpected(ErrorOr<int>(errc::invalid_argument))); + EXPECT_EQ(Orig.getError(), RoundTripped.getError()) + << "ErrorOr<T> failure value should round-trip via Expected<T> " + "conversions."; + } +} + +// Test that error messages work. +TEST(Error, ErrorMessage) { + EXPECT_EQ(toString(Error::success()).compare(""), 0); + + Error E1 = make_error<CustomError>(0); + EXPECT_EQ(toString(std::move(E1)).compare("CustomError { 0}"), 0); + + Error E2 = make_error<CustomError>(0); + handleAllErrors(std::move(E2), [](const CustomError &CE) { + EXPECT_EQ(CE.message().compare("CustomError { 0}"), 0); + }); + + Error E3 = joinErrors(make_error<CustomError>(0), make_error<CustomError>(1)); + EXPECT_EQ(toString(std::move(E3)) + .compare("CustomError { 0}\n" + "CustomError { 1}"), + 0); +} + +} // end anon namespace diff --git a/unittests/Support/Makefile b/unittests/Support/Makefile deleted file mode 100644 index 21657f12e3dc1..0000000000000 --- a/unittests/Support/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- unittests/Support/Makefile --------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -TESTNAME = Support -LINK_COMPONENTS := all-targets core support - -include $(LEVEL)/Makefile.config -include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp index 97309f8d31f5e..d373030881ec7 100644 --- a/unittests/Support/MathExtrasTest.cpp +++ b/unittests/Support/MathExtrasTest.cpp @@ -106,6 +106,40 @@ TEST(MathExtras, findLastSet) { EXPECT_EQ(5u, findLastSet(NZ64)); } +TEST(MathExtras, isIntN) { + EXPECT_TRUE(isIntN(16, 32767)); + EXPECT_FALSE(isIntN(16, 32768)); +} + +TEST(MathExtras, isUIntN) { + EXPECT_TRUE(isUIntN(16, 65535)); + EXPECT_FALSE(isUIntN(16, 65536)); + EXPECT_TRUE(isUIntN(1, 0)); + EXPECT_TRUE(isUIntN(6, 63)); +} + +TEST(MathExtras, maxIntN) { + EXPECT_EQ(32767, maxIntN(16)); + EXPECT_EQ(2147483647, maxIntN(32)); + EXPECT_EQ(std::numeric_limits<int32_t>::max(), maxIntN(32)); + EXPECT_EQ(std::numeric_limits<int64_t>::max(), maxIntN(64)); +} + +TEST(MathExtras, minIntN) { + EXPECT_EQ(-32768LL, minIntN(16)); + EXPECT_EQ(-64LL, minIntN(7)); + EXPECT_EQ(std::numeric_limits<int32_t>::min(), minIntN(32)); + EXPECT_EQ(std::numeric_limits<int64_t>::min(), minIntN(64)); +} + +TEST(MathExtras, maxUIntN) { + EXPECT_EQ(0xffffULL, maxUIntN(16)); + EXPECT_EQ(0xffffffffULL, maxUIntN(32)); + EXPECT_EQ(0xffffffffffffffffULL, maxUIntN(64)); + EXPECT_EQ(1ULL, maxUIntN(1)); + EXPECT_EQ(0x0fULL, maxUIntN(4)); +} + TEST(MathExtras, reverseBits) { uint8_t NZ8 = 42; uint16_t NZ16 = 42; @@ -163,7 +197,7 @@ TEST(MathExtras, FloatBits) { TEST(MathExtras, DoubleBits) { static const double kValue = 87987234.983498; - EXPECT_FLOAT_EQ(kValue, BitsToDouble(DoubleToBits(kValue))); + EXPECT_DOUBLE_EQ(kValue, BitsToDouble(DoubleToBits(kValue))); } TEST(MathExtras, MinAlign) { @@ -179,15 +213,15 @@ TEST(MathExtras, NextPowerOf2) { EXPECT_EQ(256u, NextPowerOf2(128)); } -TEST(MathExtras, RoundUpToAlignment) { - EXPECT_EQ(8u, RoundUpToAlignment(5, 8)); - EXPECT_EQ(24u, RoundUpToAlignment(17, 8)); - EXPECT_EQ(0u, RoundUpToAlignment(~0LL, 8)); +TEST(MathExtras, alignTo) { + EXPECT_EQ(8u, alignTo(5, 8)); + EXPECT_EQ(24u, alignTo(17, 8)); + EXPECT_EQ(0u, alignTo(~0LL, 8)); - EXPECT_EQ(7u, RoundUpToAlignment(5, 8, 7)); - EXPECT_EQ(17u, RoundUpToAlignment(17, 8, 1)); - EXPECT_EQ(3u, RoundUpToAlignment(~0LL, 8, 3)); - EXPECT_EQ(552u, RoundUpToAlignment(321, 255, 42)); + EXPECT_EQ(7u, alignTo(5, 8, 7)); + EXPECT_EQ(17u, alignTo(17, 8, 1)); + EXPECT_EQ(3u, alignTo(~0LL, 8, 3)); + EXPECT_EQ(552u, alignTo(321, 255, 42)); } template<typename T> @@ -358,4 +392,42 @@ TEST(MathExtras, SaturatingMultiplyAdd) { SaturatingMultiplyAddTestHelper<uint64_t>(); } +TEST(MathExtras, IsShiftedUInt) { + EXPECT_TRUE((isShiftedUInt<1, 0>(0))); + EXPECT_TRUE((isShiftedUInt<1, 0>(1))); + EXPECT_FALSE((isShiftedUInt<1, 0>(2))); + EXPECT_FALSE((isShiftedUInt<1, 0>(3))); + EXPECT_FALSE((isShiftedUInt<1, 0>(0x8000000000000000))); + EXPECT_TRUE((isShiftedUInt<1, 63>(0x8000000000000000))); + EXPECT_TRUE((isShiftedUInt<2, 62>(0xC000000000000000))); + EXPECT_FALSE((isShiftedUInt<2, 62>(0xE000000000000000))); + + // 0x201 is ten bits long and has a 1 in the MSB and LSB. + EXPECT_TRUE((isShiftedUInt<10, 5>(uint64_t(0x201) << 5))); + EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 4))); + EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 6))); } + +TEST(MathExtras, IsShiftedInt) { + EXPECT_TRUE((isShiftedInt<1, 0>(0))); + EXPECT_TRUE((isShiftedInt<1, 0>(-1))); + EXPECT_FALSE((isShiftedInt<1, 0>(2))); + EXPECT_FALSE((isShiftedInt<1, 0>(3))); + EXPECT_FALSE((isShiftedInt<1, 0>(0x8000000000000000))); + EXPECT_TRUE((isShiftedInt<1, 63>(0x8000000000000000))); + EXPECT_TRUE((isShiftedInt<2, 62>(0xC000000000000000))); + EXPECT_FALSE((isShiftedInt<2, 62>(0xE000000000000000))); + + // 0x201 is ten bits long and has a 1 in the MSB and LSB. + EXPECT_TRUE((isShiftedInt<11, 5>(int64_t(0x201) << 5))); + EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 3))); + EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 6))); + EXPECT_TRUE((isShiftedInt<11, 5>(-(int64_t(0x201) << 5)))); + EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 3)))); + EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 6)))); + + EXPECT_TRUE((isShiftedInt<6, 10>(-(int64_t(1) << 15)))); + EXPECT_FALSE((isShiftedInt<6, 10>(int64_t(1) << 15))); +} + +} // namespace diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 3f626f87888a3..1a6ffa50e983e 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -17,6 +17,7 @@ #include "gtest/gtest.h" #ifdef LLVM_ON_WIN32 +#include "llvm/ADT/ArrayRef.h" #include <windows.h> #include <winerror.h> #endif @@ -416,7 +417,7 @@ TEST(SupportDeathTest, TempDirectoryOnWindows) { SmallString<270> Expected{"C:\\Temp\\AB\\123456789"}; while (Expected.size() < 260) Expected.append("\\DirNameWith19Charss"); - ASSERT_EQ(260, Expected.size()); + ASSERT_EQ(260U, Expected.size()); EXPECT_TEMP_DIR(_putenv_s("TMP", Expected.c_str()), Expected.c_str()); } #endif @@ -715,6 +716,20 @@ TEST_F(FileSystemTest, DirectoryIteration) { ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0/za1")); ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0")); ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive")); + + // Test recursive_directory_iterator level() + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/reclevel/a/b/c")); + fs::recursive_directory_iterator I(Twine(TestDirectory) + "/reclevel", ec), E; + for (int l = 0; I != E; I.increment(ec), ++l) { + ASSERT_NO_ERROR(ec); + EXPECT_EQ(I.level(), l); + } + EXPECT_EQ(I, E); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a/b/c")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a/b")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel")); } const char archive[] = "!<arch>\x0A"; @@ -725,22 +740,30 @@ const char coff_bigobj[] = "\x00\x00\xff\xff\x00\x02......" const char coff_import_library[] = "\x00\x00\xff\xff...."; const char elf_relocatable[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; -const char macho_universal_binary[] = "\xca\xfe\xba\xbe...\0x00"; -const char macho_object[] = "\xfe\xed\xfa\xce..........\x00\x01"; -const char macho_executable[] = "\xfe\xed\xfa\xce..........\x00\x02"; +const char macho_universal_binary[] = "\xca\xfe\xba\xbe...\x00"; +const char macho_object[] = + "\xfe\xed\xfa\xce........\x00\x00\x00\x01............"; +const char macho_executable[] = + "\xfe\xed\xfa\xce........\x00\x00\x00\x02............"; const char macho_fixed_virtual_memory_shared_lib[] = - "\xfe\xed\xfa\xce..........\x00\x03"; -const char macho_core[] = "\xfe\xed\xfa\xce..........\x00\x04"; -const char macho_preload_executable[] = "\xfe\xed\xfa\xce..........\x00\x05"; + "\xfe\xed\xfa\xce........\x00\x00\x00\x03............"; +const char macho_core[] = + "\xfe\xed\xfa\xce........\x00\x00\x00\x04............"; +const char macho_preload_executable[] = + "\xfe\xed\xfa\xce........\x00\x00\x00\x05............"; const char macho_dynamically_linked_shared_lib[] = - "\xfe\xed\xfa\xce..........\x00\x06"; -const char macho_dynamic_linker[] = "\xfe\xed\xfa\xce..........\x00\x07"; -const char macho_bundle[] = "\xfe\xed\xfa\xce..........\x00\x08"; -const char macho_dsym_companion[] = "\xfe\xed\xfa\xce..........\x00\x0a"; -const char macho_kext_bundle[] = "\xfe\xed\xfa\xce..........\x00\x0b"; + "\xfe\xed\xfa\xce........\x00\x00\x00\x06............"; +const char macho_dynamic_linker[] = + "\xfe\xed\xfa\xce........\x00\x00\x00\x07............"; +const char macho_bundle[] = + "\xfe\xed\xfa\xce........\x00\x00\x00\x08............"; +const char macho_dsym_companion[] = + "\xfe\xed\xfa\xce........\x00\x00\x00\x0a............"; +const char macho_kext_bundle[] = + "\xfe\xed\xfa\xce........\x00\x00\x00\x0b............"; const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff"; const char macho_dynamically_linked_shared_lib_stub[] = - "\xfe\xed\xfa\xce..........\x00\x09"; + "\xfe\xed\xfa\xce........\x00\x00\x00\x09............"; TEST_F(FileSystemTest, Magic) { struct type { @@ -947,4 +970,145 @@ TEST(Support, RemoveDots) { EXPECT_EQ("c", Path1); #endif } + +TEST(Support, ReplacePathPrefix) { + SmallString<64> Path1("/foo"); + SmallString<64> Path2("/old/foo"); + SmallString<64> OldPrefix("/old"); + SmallString<64> NewPrefix("/new"); + SmallString<64> NewPrefix2("/longernew"); + SmallString<64> EmptyPrefix(""); + + SmallString<64> Path = Path1; + path::replace_path_prefix(Path, OldPrefix, NewPrefix); + EXPECT_EQ(Path, "/foo"); + Path = Path2; + path::replace_path_prefix(Path, OldPrefix, NewPrefix); + EXPECT_EQ(Path, "/new/foo"); + Path = Path2; + path::replace_path_prefix(Path, OldPrefix, NewPrefix2); + EXPECT_EQ(Path, "/longernew/foo"); + Path = Path1; + path::replace_path_prefix(Path, EmptyPrefix, NewPrefix); + EXPECT_EQ(Path, "/new/foo"); + Path = Path2; + path::replace_path_prefix(Path, OldPrefix, EmptyPrefix); + EXPECT_EQ(Path, "/foo"); +} + +TEST_F(FileSystemTest, PathFromFD) { + // Create a temp file. + int FileDescriptor; + SmallString<64> TempPath; + ASSERT_NO_ERROR( + fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); + + // Make sure it exists. + ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); + + // Try to get the path from the file descriptor + SmallString<64> ResultPath; + std::error_code ErrorCode = + fs::getPathFromOpenFD(FileDescriptor, ResultPath); + + // If we succeeded, check that the paths are the same (modulo case): + if (!ErrorCode) { + // The paths returned by createTemporaryFile and getPathFromOpenFD + // should reference the same file on disk. + fs::UniqueID D1, D2; + ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1)); + ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2)); + ASSERT_EQ(D1, D2); + } + + ::close(FileDescriptor); +} + +TEST_F(FileSystemTest, PathFromFDWin32) { + // Create a temp file. + int FileDescriptor; + SmallString<64> TempPath; + ASSERT_NO_ERROR( + fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); + + // Make sure it exists. + ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); + + SmallVector<char, 8> ResultPath; + std::error_code ErrorCode = + fs::getPathFromOpenFD(FileDescriptor, ResultPath); + + if (!ErrorCode) { + // Now that we know how much space is required for the path, create a path + // buffer with exactly enough space (sans null terminator, which should not + // be present), and call getPathFromOpenFD again to ensure that the API + // properly handles exactly-sized buffers. + SmallVector<char, 8> ExactSizedPath(ResultPath.size()); + ErrorCode = fs::getPathFromOpenFD(FileDescriptor, ExactSizedPath); + ResultPath = ExactSizedPath; + } + + if (!ErrorCode) { + fs::UniqueID D1, D2; + ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1)); + ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2)); + ASSERT_EQ(D1, D2); + } + ::close(FileDescriptor); +} + +TEST_F(FileSystemTest, PathFromFDUnicode) { + // Create a temp file. + int FileDescriptor; + SmallString<64> TempPath; + + // Test Unicode: "<temp directory>/(pi)r^2<temp rand chars>.aleth.0" + ASSERT_NO_ERROR( + fs::createTemporaryFile("\xCF\x80r\xC2\xB2", + "\xE2\x84\xB5.0", FileDescriptor, TempPath)); + + // Make sure it exists. + ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); + + SmallVector<char, 8> ResultPath; + std::error_code ErrorCode = + fs::getPathFromOpenFD(FileDescriptor, ResultPath); + + if (!ErrorCode) { + fs::UniqueID D1, D2; + ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1)); + ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2)); + ASSERT_EQ(D1, D2); + } + ::close(FileDescriptor); +} + +TEST_F(FileSystemTest, OpenFileForRead) { + // Create a temp file. + int FileDescriptor; + SmallString<64> TempPath; + ASSERT_NO_ERROR( + fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); + + // Make sure it exists. + ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); + + // Open the file for read + int FileDescriptor2; + SmallString<64> ResultPath; + ASSERT_NO_ERROR( + fs::openFileForRead(Twine(TempPath), FileDescriptor2, &ResultPath)) + + // If we succeeded, check that the paths are the same (modulo case): + if (!ResultPath.empty()) { + // The paths returned by createTemporaryFile and getPathFromOpenFD + // should reference the same file on disk. + fs::UniqueID D1, D2; + ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1)); + ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2)); + ASSERT_EQ(D1, D2); + } + + ::close(FileDescriptor); +} } // anonymous namespace diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index 47a3dbb5fb1f1..886ead8305bc1 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -223,7 +223,7 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) { ProcessInfo PI1 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0, &Error, &ExecutionFailed); ASSERT_FALSE(ExecutionFailed) << Error; - ASSERT_NE(PI1.Pid, 0) << "Invalid process id"; + ASSERT_NE(PI1.Pid, ProcessInfo::InvalidPid) << "Invalid process id"; unsigned LoopCount = 0; @@ -231,7 +231,7 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) { // LoopCount should only be incremented once. while (true) { ++LoopCount; - ProcessInfo WaitResult = Wait(PI1, 0, true, &Error); + ProcessInfo WaitResult = llvm::sys::Wait(PI1, 0, true, &Error); ASSERT_TRUE(Error.empty()); if (WaitResult.Pid == PI1.Pid) break; @@ -242,13 +242,13 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) { ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0, &Error, &ExecutionFailed); ASSERT_FALSE(ExecutionFailed) << Error; - ASSERT_NE(PI2.Pid, 0) << "Invalid process id"; + ASSERT_NE(PI2.Pid, ProcessInfo::InvalidPid) << "Invalid process id"; // Test that Wait() with SecondsToWait=0 performs a non-blocking wait. In this // cse, LoopCount should be greater than 1 (more than one increment occurs). while (true) { ++LoopCount; - ProcessInfo WaitResult = Wait(PI2, 0, false, &Error); + ProcessInfo WaitResult = llvm::sys::Wait(PI2, 0, false, &Error); ASSERT_TRUE(Error.empty()); if (WaitResult.Pid == PI2.Pid) break; @@ -304,7 +304,7 @@ TEST(ProgramTest, TestExecuteNegative) { bool ExecutionFailed; ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, nullptr, 0, &Error, &ExecutionFailed); - ASSERT_EQ(PI.Pid, 0) + ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid) << "On error ExecuteNoWait should return an invalid ProcessInfo"; ASSERT_TRUE(ExecutionFailed); ASSERT_FALSE(Error.empty()); diff --git a/unittests/Support/StreamingMemoryObject.cpp b/unittests/Support/StreamingMemoryObject.cpp deleted file mode 100644 index e86aa9cae51e8..0000000000000 --- a/unittests/Support/StreamingMemoryObject.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===- llvm/unittest/Support/StreamingMemoryObject.cpp - unit tests -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/StreamingMemoryObject.h" -#include "gtest/gtest.h" -#include <string.h> - -using namespace llvm; - -namespace { -class NullDataStreamer : public DataStreamer { - size_t GetBytes(unsigned char *buf, size_t len) override { - memset(buf, 0, len); - return len; - } -}; -} - -TEST(StreamingMemoryObject, Test) { - auto DS = make_unique<NullDataStreamer>(); - StreamingMemoryObject O(std::move(DS)); - EXPECT_TRUE(O.isValidAddress(32 * 1024)); -} - -TEST(StreamingMemoryObject, TestSetKnownObjectSize) { - auto DS = make_unique<NullDataStreamer>(); - StreamingMemoryObject O(std::move(DS)); - uint8_t Buf[32]; - EXPECT_EQ((uint64_t) 16, O.readBytes(Buf, 16, 0)); - O.setKnownObjectSize(24); - EXPECT_EQ((uint64_t) 8, O.readBytes(Buf, 16, 16)); -} diff --git a/unittests/Support/StreamingMemoryObjectTest.cpp b/unittests/Support/StreamingMemoryObjectTest.cpp new file mode 100644 index 0000000000000..836dfa9084f5b --- /dev/null +++ b/unittests/Support/StreamingMemoryObjectTest.cpp @@ -0,0 +1,68 @@ +//===- unittests/Support/StreamingMemoryObjectTest.cpp --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/StreamingMemoryObject.h" +#include "gtest/gtest.h" +#include <string.h> + +using namespace llvm; + +namespace { + +class NullDataStreamer : public DataStreamer { + size_t GetBytes(unsigned char *Buffer, size_t Length) override { + memset(Buffer, 0, Length); + return Length; + } +}; + +class BufferStreamer : public DataStreamer { + StringRef Buffer; + +public: + BufferStreamer(StringRef Buffer) : Buffer(Buffer) {} + size_t GetBytes(unsigned char *OutBuffer, size_t Length) override { + if (Length >= Buffer.size()) + Length = Buffer.size(); + + std::copy(Buffer.begin(), Buffer.begin() + Length, OutBuffer); + Buffer = Buffer.drop_front(Length); + return Length; + } +}; + +TEST(StreamingMemoryObjectTest, isValidAddress) { + auto DS = make_unique<NullDataStreamer>(); + StreamingMemoryObject O(std::move(DS)); + EXPECT_TRUE(O.isValidAddress(32 * 1024)); +} + +TEST(StreamingMemoryObjectTest, setKnownObjectSize) { + auto DS = make_unique<NullDataStreamer>(); + StreamingMemoryObject O(std::move(DS)); + uint8_t Buf[32]; + EXPECT_EQ(16u, O.readBytes(Buf, 16, 0)); + O.setKnownObjectSize(24); + EXPECT_EQ(8u, O.readBytes(Buf, 16, 16)); +} + +TEST(StreamingMemoryObjectTest, getPointer) { + uint8_t InputBuffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + StreamingMemoryObject O(make_unique<BufferStreamer>(StringRef( + reinterpret_cast<const char *>(InputBuffer), sizeof(InputBuffer)))); + + EXPECT_TRUE(std::equal(InputBuffer + 1, InputBuffer + 2, O.getPointer(1, 2))); + EXPECT_TRUE(std::equal(InputBuffer + 3, InputBuffer + 7, O.getPointer(3, 4))); + EXPECT_TRUE(std::equal(InputBuffer + 4, InputBuffer + 8, O.getPointer(4, 5))); + EXPECT_TRUE(std::equal(InputBuffer, InputBuffer + 8, O.getPointer(0, 20))); +} + +} // end namespace diff --git a/unittests/Support/TargetParserTest.cpp b/unittests/Support/TargetParserTest.cpp new file mode 100644 index 0000000000000..21994f27b73cd --- /dev/null +++ b/unittests/Support/TargetParserTest.cpp @@ -0,0 +1,92 @@ +//===----------- TargetParser.cpp - Target Parser -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/Support/TargetParser.h" + +using namespace llvm; + +namespace { +static const unsigned kAArch64ArchKinds[] = { +#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, \ + ARCH_BASE_EXT) \ + llvm::ARM::ID, +#include "llvm/Support/AArch64TargetParser.def" +#undef AARCH64_ARCH +}; + +template <typename T, size_t N> +bool contains(const T (&array)[N], const T element) { + return std::find(std::begin(array), std::end(array), element) != + std::end(array); +} + +TEST(TargetParserTest, ARMArchName) { + for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0); + AK <= ARM::ArchKind::AK_LAST; + AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1)) + EXPECT_TRUE(AK == ARM::AK_LAST ? ARM::getArchName(AK).empty() + : !ARM::getArchName(AK).empty()); +} + +TEST(TargetParserTest, ARMCPUAttr) { + for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0); + AK <= ARM::ArchKind::AK_LAST; + AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1)) + EXPECT_TRUE((AK == ARM::AK_INVALID || AK == ARM::AK_LAST) + ? ARM::getCPUAttr(AK).empty() + : !ARM::getCPUAttr(AK).empty()); +} + +TEST(TargetParserTest, ARMSubArch) { + for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0); + AK <= ARM::ArchKind::AK_LAST; + AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1)) + EXPECT_TRUE((AK == ARM::AK_INVALID || AK == ARM::AK_IWMMXT || + AK == ARM::AK_IWMMXT2 || AK == ARM::AK_LAST) + ? ARM::getSubArch(AK).empty() + : !ARM::getSubArch(AK).empty()); +} + +TEST(TargetParserTest, ARMFPUName) { + for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0); + FK <= ARM::FPUKind::FK_LAST; + FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1)) + EXPECT_TRUE(FK == ARM::FK_LAST ? ARM::getFPUName(FK).empty() + : !ARM::getFPUName(FK).empty()); +} + +TEST(TargetParserTest, AArch64ArchName) { + for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0); + AK <= ARM::ArchKind::AK_LAST; + AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1)) + EXPECT_TRUE(contains(kAArch64ArchKinds, static_cast<unsigned>(AK)) + ? !AArch64::getArchName(AK).empty() + : AArch64::getArchName(AK).empty()); +} + +TEST(TargetParserTest, AArch64CPUAttr) { + for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0); + AK <= ARM::ArchKind::AK_LAST; + AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1)) + EXPECT_TRUE(contains(kAArch64ArchKinds, static_cast<unsigned>(AK)) + ? !AArch64::getCPUAttr(AK).empty() + : AArch64::getCPUAttr(AK).empty()); +} + +TEST(TargetParserTest, AArch64SubArch) { + for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0); + AK <= ARM::ArchKind::AK_LAST; + AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1)) + EXPECT_TRUE(contains(kAArch64ArchKinds, static_cast<unsigned>(AK)) + ? !AArch64::getSubArch(AK).empty() + : AArch64::getSubArch(AK).empty()); +} +} + diff --git a/unittests/Support/TargetRegistry.cpp b/unittests/Support/TargetRegistry.cpp deleted file mode 100644 index ae89c8b649303..0000000000000 --- a/unittests/Support/TargetRegistry.cpp +++ /dev/null @@ -1,42 +0,0 @@ -//===- unittests/Support/TargetRegistry.cpp - -----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -TEST(TargetRegistry, TargetHasArchType) { - // Presence of at least one target will be asserted when done with the loop, - // else this would pass by accident if InitializeAllTargetInfos were omitted. - int Count = 0; - - llvm::InitializeAllTargetInfos(); - - for (const Target &T : TargetRegistry::targets()) { - StringRef Name = T.getName(); - // There is really no way (at present) to ask a Target whether it targets - // a specific architecture, because the logic for that is buried in a - // predicate. - // We can't ask the predicate "Are you a function that always returns - // false?" - // So given that the cpp backend truly has no target arch, it is skipped. - if (Name != "cpp") { - Triple::ArchType Arch = Triple::getArchTypeForLLVMName(Name); - EXPECT_NE(Arch, Triple::UnknownArch); - ++Count; - } - } - ASSERT_NE(Count, 0); -} - -} // end namespace diff --git a/unittests/Support/ThreadPool.cpp b/unittests/Support/ThreadPool.cpp index 0f36c383d494c..69a24bc5444c0 100644 --- a/unittests/Support/ThreadPool.cpp +++ b/unittests/Support/ThreadPool.cpp @@ -135,7 +135,7 @@ TEST_F(ThreadPoolTest, Async) { TEST_F(ThreadPoolTest, GetFuture) { CHECK_UNSUPPORTED(); - ThreadPool Pool; + ThreadPool Pool{2}; std::atomic_int i{0}; Pool.async([this, &i] { waitForMainThread(); diff --git a/unittests/Support/TrailingObjectsTest.cpp b/unittests/Support/TrailingObjectsTest.cpp index 866ff1e6e88d8..a1d3e7b3c8645 100644 --- a/unittests/Support/TrailingObjectsTest.cpp +++ b/unittests/Support/TrailingObjectsTest.cpp @@ -34,6 +34,7 @@ public: void *Mem = ::operator new(totalSizeToAlloc<short>(NumShorts)); return new (Mem) Class1(ShortArray, NumShorts); } + void operator delete(void *p) { ::operator delete(p); } short get(unsigned Num) const { return getTrailingObjects<short>()[Num]; } @@ -78,6 +79,7 @@ public: *C->getTrailingObjects<double>() = D; return C; } + void operator delete(void *p) { ::operator delete(p); } short getShort() const { if (!HasShort) @@ -118,8 +120,8 @@ TEST(TrailingObjects, TwoArg) { Class2 *C1 = Class2::create(4); Class2 *C2 = Class2::create(0, 4.2); - EXPECT_EQ(sizeof(Class2), llvm::RoundUpToAlignment(sizeof(bool) * 2, - llvm::alignOf<double>())); + EXPECT_EQ(sizeof(Class2), + llvm::alignTo(sizeof(bool) * 2, llvm::alignOf<double>())); EXPECT_EQ(llvm::alignOf<Class2>(), llvm::alignOf<double>()); EXPECT_EQ((Class2::additionalSizeToAlloc<double, short>(1, 0)), @@ -162,8 +164,7 @@ class Class3 final : public TrailingObjects<Class3, double, short, bool> { TEST(TrailingObjects, ThreeArg) { EXPECT_EQ((Class3::additionalSizeToAlloc<double, short, bool>(1, 1, 3)), sizeof(double) + sizeof(short) + 3 * sizeof(bool)); - EXPECT_EQ(sizeof(Class3), - llvm::RoundUpToAlignment(1, llvm::alignOf<double>())); + EXPECT_EQ(sizeof(Class3), llvm::alignTo(1, llvm::alignOf<double>())); std::unique_ptr<char[]> P(new char[1000]); Class3 *C = reinterpret_cast<Class3 *>(P.get()); EXPECT_EQ(C->getTrailingObjects<double>(), reinterpret_cast<double *>(C + 1)); @@ -183,8 +184,8 @@ class Class4 final : public TrailingObjects<Class4, char, long> { TEST(TrailingObjects, Realignment) { EXPECT_EQ((Class4::additionalSizeToAlloc<char, long>(1, 1)), - llvm::RoundUpToAlignment(sizeof(long) + 1, llvm::alignOf<long>())); - EXPECT_EQ(sizeof(Class4), llvm::RoundUpToAlignment(1, llvm::alignOf<long>())); + llvm::alignTo(sizeof(long) + 1, llvm::alignOf<long>())); + EXPECT_EQ(sizeof(Class4), llvm::alignTo(1, llvm::alignOf<long>())); std::unique_ptr<char[]> P(new char[1000]); Class4 *C = reinterpret_cast<Class4 *>(P.get()); EXPECT_EQ(C->getTrailingObjects<char>(), reinterpret_cast<char *>(C + 1)); diff --git a/unittests/Support/TypeNameTest.cpp b/unittests/Support/TypeNameTest.cpp new file mode 100644 index 0000000000000..63381d46f02fe --- /dev/null +++ b/unittests/Support/TypeNameTest.cpp @@ -0,0 +1,49 @@ +//===- TypeNameTest.cpp ---------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/TypeName.h" +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { +namespace N1 { +struct S1 {}; +class C1 {}; +union U1 {}; +} + +TEST(TypeNameTest, Names) { + struct S2 {}; + + StringRef S1Name = getTypeName<N1::S1>(); + StringRef C1Name = getTypeName<N1::C1>(); + StringRef U1Name = getTypeName<N1::U1>(); + StringRef S2Name = getTypeName<S2>(); + +#if defined(__clang__) || defined(__GNUC__) || defined(__INTEL_COMPILER) || \ + defined(_MSC_VER) + EXPECT_TRUE(S1Name.endswith("::N1::S1")) << S1Name.str(); + EXPECT_TRUE(C1Name.endswith("::N1::C1")) << C1Name.str(); + EXPECT_TRUE(U1Name.endswith("::N1::U1")) << U1Name.str(); +#ifdef __clang__ + EXPECT_TRUE(S2Name.endswith("S2")) << S2Name.str(); +#else + EXPECT_TRUE(S2Name.endswith("::S2")) << S2Name.str(); +#endif +#else + EXPECT_EQ("UNKNOWN_TYPE", S1Name); + EXPECT_EQ("UNKNOWN_TYPE", C1Name); + EXPECT_EQ("UNKNOWN_TYPE", U1Name); + EXPECT_EQ("UNKNOWN_TYPE", S2Name); +#endif +} + +} // end anonymous namespace diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index e7affa1698dcc..5f35a802caa5e 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/Format.h" #include "llvm/Support/YAMLTraits.h" #include "gtest/gtest.h" @@ -389,6 +389,111 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) { } } +//===----------------------------------------------------------------------===// +// Test endian-aware types +//===----------------------------------------------------------------------===// + +struct EndianTypes { + typedef llvm::support::detail::packed_endian_specific_integral< + float, llvm::support::little, llvm::support::unaligned> + ulittle_float; + typedef llvm::support::detail::packed_endian_specific_integral< + double, llvm::support::little, llvm::support::unaligned> + ulittle_double; + + llvm::support::ulittle64_t u64; + llvm::support::ulittle32_t u32; + llvm::support::ulittle16_t u16; + llvm::support::little64_t s64; + llvm::support::little32_t s32; + llvm::support::little16_t s16; + ulittle_float f; + ulittle_double d; +}; + +namespace llvm { +namespace yaml { +template <> struct MappingTraits<EndianTypes> { + static void mapping(IO &io, EndianTypes &et) { + io.mapRequired("u64", et.u64); + io.mapRequired("u32", et.u32); + io.mapRequired("u16", et.u16); + io.mapRequired("s64", et.s64); + io.mapRequired("s32", et.s32); + io.mapRequired("s16", et.s16); + io.mapRequired("f", et.f); + io.mapRequired("d", et.d); + } +}; +} +} + +// +// Test the reading of all endian scalar conversions +// +TEST(YAMLIO, TestReadEndianTypes) { + EndianTypes map; + Input yin("---\n" + "u64: 5000000000\n" + "u32: 4000000000\n" + "u16: 65000\n" + "s64: -5000000000\n" + "s32: -2000000000\n" + "s16: -32000\n" + "f: 3.25\n" + "d: -2.8625\n" + "...\n"); + yin >> map; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(map.u64, 5000000000ULL); + EXPECT_EQ(map.u32, 4000000000U); + EXPECT_EQ(map.u16, 65000); + EXPECT_EQ(map.s64, -5000000000LL); + EXPECT_EQ(map.s32, -2000000000L); + EXPECT_EQ(map.s16, -32000); + EXPECT_EQ(map.f, 3.25f); + EXPECT_EQ(map.d, -2.8625); +} + +// +// Test writing then reading back all endian-aware scalar types +// +TEST(YAMLIO, TestReadWriteEndianTypes) { + std::string intermediate; + { + EndianTypes map; + map.u64 = 6000000000ULL; + map.u32 = 3000000000U; + map.u16 = 50000; + map.s64 = -6000000000LL; + map.s32 = -2000000000; + map.s16 = -32000; + map.f = 3.25f; + map.d = -2.8625; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + } + + { + Input yin(intermediate); + EndianTypes map; + yin >> map; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(map.u64, 6000000000ULL); + EXPECT_EQ(map.u32, 3000000000U); + EXPECT_EQ(map.u16, 50000); + EXPECT_EQ(map.s64, -6000000000LL); + EXPECT_EQ(map.s32, -2000000000L); + EXPECT_EQ(map.s16, -32000); + EXPECT_EQ(map.f, 3.25f); + EXPECT_EQ(map.d, -2.8625); + } +} + struct StringTypes { llvm::StringRef str1; llvm::StringRef str2; diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp index 41ad649699caa..3f12a53fd9c59 100644 --- a/unittests/Support/YAMLParserTest.cpp +++ b/unittests/Support/YAMLParserTest.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Casting.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index ff986025b2ccb..ed6ddabe46348 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -70,8 +70,8 @@ TEST(raw_ostreamTest, Types_Buffered) { // void* EXPECT_EQ("0x0", printToString((void*) nullptr)); - EXPECT_EQ("0xbeef", printToString((void*) 0xbeef)); - EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeef)); + EXPECT_EQ("0xbeef", printToString((void*) 0xbeefLL)); + EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeefLL)); // Min and max. EXPECT_EQ("18446744073709551615", printToString(UINT64_MAX)); @@ -101,8 +101,8 @@ TEST(raw_ostreamTest, Types_Unbuffered) { // void* EXPECT_EQ("0x0", printToStringUnbuffered((void*) nullptr)); - EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeef)); - EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeef)); + EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeefLL)); + EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeefLL)); // Min and max. EXPECT_EQ("18446744073709551615", printToStringUnbuffered(UINT64_MAX)); diff --git a/unittests/Support/raw_sha1_ostream_test.cpp b/unittests/Support/raw_sha1_ostream_test.cpp new file mode 100644 index 0000000000000..db2a3e9ab643e --- /dev/null +++ b/unittests/Support/raw_sha1_ostream_test.cpp @@ -0,0 +1,71 @@ +//===- llvm/unittest/Support/raw_ostream_test.cpp - raw_ostream tests -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_sha1_ostream.h" + +#include <string> + +using namespace llvm; + +static std::string toHex(StringRef Input) { + static const char *const LUT = "0123456789ABCDEF"; + size_t Length = Input.size(); + + std::string Output; + Output.reserve(2 * Length); + for (size_t i = 0; i < Length; ++i) { + const unsigned char c = Input[i]; + Output.push_back(LUT[c >> 4]); + Output.push_back(LUT[c & 15]); + } + return Output; +} + +TEST(raw_sha1_ostreamTest, Basic) { + llvm::raw_sha1_ostream Sha1Stream; + Sha1Stream << "Hello World!"; + auto Hash = toHex(Sha1Stream.sha1()); + + ASSERT_EQ("2EF7BDE608CE5404E97D5F042F95F89F1C232871", Hash); +} + +// Check that getting the intermediate hash in the middle of the stream does +// not invalidate the final result. +TEST(raw_sha1_ostreamTest, Intermediate) { + llvm::raw_sha1_ostream Sha1Stream; + Sha1Stream << "Hello"; + auto Hash = toHex(Sha1Stream.sha1()); + + ASSERT_EQ("F7FF9E8B7BB2E09B70935A5D785E0CC5D9D0ABF0", Hash); + Sha1Stream << " World!"; + Hash = toHex(Sha1Stream.sha1()); + + // Compute the non-split hash separately as a reference. + llvm::raw_sha1_ostream NonSplitSha1Stream; + NonSplitSha1Stream << "Hello World!"; + auto NonSplitHash = toHex(NonSplitSha1Stream.sha1()); + + ASSERT_EQ(NonSplitHash, Hash); +} + +TEST(raw_sha1_ostreamTest, Reset) { + llvm::raw_sha1_ostream Sha1Stream; + Sha1Stream << "Hello"; + auto Hash = toHex(Sha1Stream.sha1()); + + ASSERT_EQ("F7FF9E8B7BB2E09B70935A5D785E0CC5D9D0ABF0", Hash); + + Sha1Stream.resetHash(); + Sha1Stream << " World!"; + Hash = toHex(Sha1Stream.sha1()); + + ASSERT_EQ("7447F2A5A42185C8CF91E632789C431830B59067", Hash); +} |