diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
commit | 5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch) | |
tree | a6140557876943cdd800ee997c9317283394b22c /unittests/Support | |
parent | f03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff) |
Diffstat (limited to 'unittests/Support')
23 files changed, 1089 insertions, 54 deletions
diff --git a/unittests/Support/AlignOfTest.cpp b/unittests/Support/AlignOfTest.cpp index 40f729585728c..e0859fc747f4c 100644 --- a/unittests/Support/AlignOfTest.cpp +++ b/unittests/Support/AlignOfTest.cpp @@ -7,6 +7,12 @@ // //===----------------------------------------------------------------------===// +#ifdef _MSC_VER +// Disable warnings about alignment-based structure padding. +// This must be above the includes to suppress warnings in included templates. +#pragma warning(disable:4324) +#endif + #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include "gtest/gtest.h" @@ -22,35 +28,21 @@ namespace { // Suppress direct base '{anonymous}::S1' inaccessible in '{anonymous}::D9' // due to ambiguity warning. -// +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Winaccessible-base" +#elif ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 // Pragma based warning suppression was introduced in GGC 4.2. Additionally // this warning is "enabled by default". The warning still appears if -Wall is // suppressed. Apparently GCC suppresses it when -w is specifed, which is odd. -// At any rate, clang on the other hand gripes about -Wunknown-pragma, so -// leaving it out of this. -#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 && !defined(__clang__) #pragma GCC diagnostic warning "-w" #endif // Define some fixed alignment types to use in these tests. -#if __has_feature(cxx_alignas) -struct alignas(1) A1 { }; -struct alignas(2) A2 { }; -struct alignas(4) A4 { }; -struct alignas(8) A8 { }; -#elif defined(__GNUC__) -struct A1 { } __attribute__((aligned(1))); -struct A2 { } __attribute__((aligned(2))); -struct A4 { } __attribute__((aligned(4))); -struct A8 { } __attribute__((aligned(8))); -#elif defined(_MSC_VER) -__declspec(align(1)) struct A1 { }; -__declspec(align(2)) struct A2 { }; -__declspec(align(4)) struct A4 { }; -__declspec(align(8)) struct A8 { }; -#else -# error No supported align as directive. -#endif +struct LLVM_ALIGNAS(1) A1 {}; +struct LLVM_ALIGNAS(2) A2 {}; +struct LLVM_ALIGNAS(4) A4 {}; +struct LLVM_ALIGNAS(8) A8 {}; struct S1 {}; struct S2 { char a; }; @@ -69,12 +61,22 @@ struct D8 : S1, D4, D5 { double x[2]; }; struct D9 : S1, D1 { S1 s1; }; struct V1 { virtual ~V1(); }; struct V2 { int x; virtual ~V2(); }; -struct V3 : V1 { virtual ~V3(); }; -struct V4 : virtual V2 { int y; virtual ~V4(); }; -struct V5 : V4, V3 { double z; virtual ~V5(); }; +struct V3 : V1 { + ~V3() override; +}; +struct V4 : virtual V2 { int y; + ~V4() override; +}; +struct V5 : V4, V3 { double z; + ~V5() override; +}; struct V6 : S1 { virtual ~V6(); }; -struct V7 : virtual V2, virtual V6 { virtual ~V7(); }; -struct V8 : V5, virtual V6, V7 { double zz; virtual ~V8(); }; +struct V7 : virtual V2, virtual V6 { + ~V7() override; +}; +struct V8 : V5, virtual V6, V7 { double zz; + ~V8() override; +}; double S6::f() { return 0.0; } float D2::g() { return 0.0f; } diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index 7f15776d6f007..38c7fcba8afd4 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -61,6 +61,13 @@ TEST(AllocatorTest, ThreeSlabs) { // again. TEST(AllocatorTest, TestReset) { BumpPtrAllocator Alloc; + + // Allocate something larger than the SizeThreshold=4096. + (void)Alloc.Allocate(5000, 1); + Alloc.Reset(); + // Calling Reset should free all CustomSizedSlabs. + EXPECT_EQ(0u, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); Alloc.Allocate(3000, 1); diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp index f6e3537de91a9..0eac8bb8811bc 100644 --- a/unittests/Support/BlockFrequencyTest.cpp +++ b/unittests/Support/BlockFrequencyTest.cpp @@ -1,3 +1,12 @@ +//===- unittests/Support/BlockFrequencyTest.cpp - BlockFrequency 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/BlockFrequency.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/DataTypes.h" diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index dd270ccea42de..564d189d49c2b 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} Support ) @@ -13,6 +14,8 @@ add_llvm_unittest(SupportTests CompressionTest.cpp ConvertUTFTest.cpp DataExtractorTest.cpp + DwarfTest.cpp + EndianStreamTest.cpp EndianTest.cpp ErrorOrTest.cpp FileOutputBufferTest.cpp @@ -35,6 +38,7 @@ add_llvm_unittest(SupportTests StreamingMemoryObject.cpp StringPool.cpp SwapByteOrderTest.cpp + TargetRegistry.cpp ThreadLocalTest.cpp TimeValueTest.cpp UnicodeTest.cpp @@ -42,6 +46,7 @@ add_llvm_unittest(SupportTests YAMLParserTest.cpp formatted_raw_ostream_test.cpp raw_ostream_test.cpp + raw_pwrite_stream_test.cpp ) # ManagedStatic.cpp uses <pthread>. diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp index 3218189eeab6c..e6c35fc21eb7d 100644 --- a/unittests/Support/Casting.cpp +++ b/unittests/Support/Casting.cpp @@ -250,7 +250,7 @@ class PTy { Base *B; public: PTy(Base *B) : B(B) {} - LLVM_EXPLICIT operator bool() const { return get(); } + explicit operator bool() const { return get(); } Base *get() const { return B; } }; diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index ac8d3d8c9d633..328c4b7fcf300 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -35,6 +35,8 @@ class TempEnvVar { #if HAVE_SETENV // Assume setenv and unsetenv come together. unsetenv(name); +#else + (void)name; // Suppress -Wunused-private-field. #endif } @@ -63,21 +65,19 @@ public: StackOption(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) : Base(M0, M1, M2, M3) {} - ~StackOption() { - this->removeArgument(); - } + ~StackOption() override { this->removeArgument(); } }; cl::OptionCategory TestCategory("Test Options", "Description"); -cl::opt<int> TestOption("test-option", cl::desc("old description")); TEST(CommandLineTest, ModifyExisitingOption) { + StackOption<int> TestOption("test-option", cl::desc("old description")); + const char Description[] = "New description"; const char ArgString[] = "new-test-option"; const char ValueString[] = "Integer"; - StringMap<cl::Option*> Map; - cl::getRegisteredOptions(Map); + StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); ASSERT_TRUE(Map.count("test-option") == 1) << "Could not find option in map."; @@ -230,5 +230,44 @@ TEST(CommandLineTest, AliasRequired) { testAliasRequired(array_lengthof(opts2), opts2); } +TEST(CommandLineTest, HideUnrelatedOptions) { + StackOption<int> TestOption1("hide-option-1"); + StackOption<int> TestOption2("hide-option-2", cl::cat(TestCategory)); + + cl::HideUnrelatedOptions(TestCategory); + + ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag()) + << "Failed to hide extra option."; + ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag()) + << "Hid extra option that should be visable."; + + StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); + ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag()) + << "Hid default option that should be visable."; +} + +cl::OptionCategory TestCategory2("Test Options set 2", "Description"); + +TEST(CommandLineTest, HideUnrelatedOptionsMulti) { + StackOption<int> TestOption1("multi-hide-option-1"); + StackOption<int> TestOption2("multi-hide-option-2", cl::cat(TestCategory)); + StackOption<int> TestOption3("multi-hide-option-3", cl::cat(TestCategory2)); + + const cl::OptionCategory *VisibleCategories[] = {&TestCategory, + &TestCategory2}; + + cl::HideUnrelatedOptions(makeArrayRef(VisibleCategories)); + + ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag()) + << "Failed to hide extra option."; + ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag()) + << "Hid extra option that should be visable."; + ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag()) + << "Hid extra option that should be visable."; + + StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); + ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag()) + << "Hid default option that should be visable."; +} } // anonymous namespace diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index 49748db4ae971..d436fc0228963 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Format.h" #include "gtest/gtest.h" #include <string> #include <utility> @@ -37,6 +38,19 @@ TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) { EXPECT_EQ(Expected, Result); } +TEST(ConvertUTFTest, ConvertUTF8ToUTF16String) { + // Src is the look of disapproval. + static const char Src[] = "\xe0\xb2\xa0_\xe0\xb2\xa0"; + StringRef Ref(Src, sizeof(Src) - 1); + SmallVector<UTF16, 5> Result; + bool Success = convertUTF8ToUTF16String(Ref, Result); + EXPECT_TRUE(Success); + static const UTF16 Expected[] = {0x0CA0, 0x005f, 0x0CA0, 0}; + ASSERT_EQ(3u, Result.size()); + for (int I = 0, E = 3; I != E; ++I) + EXPECT_EQ(Expected[I], Result[I]); +} + TEST(ConvertUTFTest, OddLengthInput) { std::string Result; bool Success = convertUTF16ToUTF8String(makeArrayRef("xxxxx", 5), Result); diff --git a/unittests/Support/DwarfTest.cpp b/unittests/Support/DwarfTest.cpp new file mode 100644 index 0000000000000..74fcc989b45a2 --- /dev/null +++ b/unittests/Support/DwarfTest.cpp @@ -0,0 +1,141 @@ +//===- unittest/Support/DwarfTest.cpp - Dwarf support 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/Dwarf.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::dwarf; + +namespace { + +TEST(DwarfTest, TagStringOnInvalid) { + // This is invalid, so it shouldn't be stringified. + EXPECT_EQ(nullptr, TagString(DW_TAG_invalid)); + + // These aren't really tags: they describe ranges within tags. They + // shouldn't be stringified either. + EXPECT_EQ(nullptr, TagString(DW_TAG_lo_user)); + EXPECT_EQ(nullptr, TagString(DW_TAG_hi_user)); + EXPECT_EQ(nullptr, TagString(DW_TAG_user_base)); +} + +TEST(DwarfTest, getTag) { + // A couple of valid tags. + EXPECT_EQ(DW_TAG_array_type, getTag("DW_TAG_array_type")); + EXPECT_EQ(DW_TAG_module, getTag("DW_TAG_module")); + + // Invalid tags. + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_invalid")); + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_madeuptag")); + EXPECT_EQ(DW_TAG_invalid, getTag("something else")); + + // Tag range markers should not be recognized. + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_lo_user")); + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_hi_user")); + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_user_base")); +} + +TEST(DwarfTest, getOperationEncoding) { + // Some valid ops. + EXPECT_EQ(DW_OP_deref, getOperationEncoding("DW_OP_deref")); + EXPECT_EQ(DW_OP_bit_piece, getOperationEncoding("DW_OP_bit_piece")); + + // Invalid ops. + EXPECT_EQ(0u, getOperationEncoding("DW_OP_otherthings")); + EXPECT_EQ(0u, getOperationEncoding("other")); + + // Markers shouldn't be recognized. + EXPECT_EQ(0u, getOperationEncoding("DW_OP_lo_user")); + EXPECT_EQ(0u, getOperationEncoding("DW_OP_hi_user")); +} + +TEST(DwarfTest, LanguageStringOnInvalid) { + // This is invalid, so it shouldn't be stringified. + EXPECT_EQ(nullptr, LanguageString(0)); + + // These aren't really tags: they describe ranges within tags. They + // shouldn't be stringified either. + EXPECT_EQ(nullptr, LanguageString(DW_LANG_lo_user)); + EXPECT_EQ(nullptr, LanguageString(DW_LANG_hi_user)); +} + +TEST(DwarfTest, getLanguage) { + // A couple of valid languages. + EXPECT_EQ(DW_LANG_C89, getLanguage("DW_LANG_C89")); + EXPECT_EQ(DW_LANG_C_plus_plus_11, getLanguage("DW_LANG_C_plus_plus_11")); + EXPECT_EQ(DW_LANG_OCaml, getLanguage("DW_LANG_OCaml")); + EXPECT_EQ(DW_LANG_Mips_Assembler, getLanguage("DW_LANG_Mips_Assembler")); + + // Invalid languages. + EXPECT_EQ(0u, getLanguage("DW_LANG_invalid")); + EXPECT_EQ(0u, getLanguage("DW_TAG_array_type")); + EXPECT_EQ(0u, getLanguage("something else")); + + // Language range markers should not be recognized. + EXPECT_EQ(0u, getLanguage("DW_LANG_lo_user")); + EXPECT_EQ(0u, getLanguage("DW_LANG_hi_user")); +} + +TEST(DwarfTest, AttributeEncodingStringOnInvalid) { + // This is invalid, so it shouldn't be stringified. + EXPECT_EQ(nullptr, AttributeEncodingString(0)); + + // These aren't really tags: they describe ranges within tags. They + // shouldn't be stringified either. + EXPECT_EQ(nullptr, AttributeEncodingString(DW_ATE_lo_user)); + EXPECT_EQ(nullptr, AttributeEncodingString(DW_ATE_hi_user)); +} + +TEST(DwarfTest, getAttributeEncoding) { + // A couple of valid languages. + EXPECT_EQ(DW_ATE_boolean, getAttributeEncoding("DW_ATE_boolean")); + EXPECT_EQ(DW_ATE_imaginary_float, + getAttributeEncoding("DW_ATE_imaginary_float")); + + // Invalid languages. + EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_invalid")); + EXPECT_EQ(0u, getAttributeEncoding("DW_TAG_array_type")); + EXPECT_EQ(0u, getAttributeEncoding("something else")); + + // AttributeEncoding range markers should not be recognized. + EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_lo_user")); + EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_hi_user")); +} + +TEST(DwarfTest, VirtualityString) { + EXPECT_EQ(StringRef("DW_VIRTUALITY_none"), + VirtualityString(DW_VIRTUALITY_none)); + EXPECT_EQ(StringRef("DW_VIRTUALITY_virtual"), + VirtualityString(DW_VIRTUALITY_virtual)); + EXPECT_EQ(StringRef("DW_VIRTUALITY_pure_virtual"), + VirtualityString(DW_VIRTUALITY_pure_virtual)); + + // DW_VIRTUALITY_max should be pure virtual. + EXPECT_EQ(StringRef("DW_VIRTUALITY_pure_virtual"), + VirtualityString(DW_VIRTUALITY_max)); + + // Invalid numbers shouldn't be stringified. + EXPECT_EQ(nullptr, VirtualityString(DW_VIRTUALITY_max + 1)); + EXPECT_EQ(nullptr, VirtualityString(DW_VIRTUALITY_max + 77)); +} + +TEST(DwarfTest, getVirtuality) { + EXPECT_EQ(DW_VIRTUALITY_none, getVirtuality("DW_VIRTUALITY_none")); + EXPECT_EQ(DW_VIRTUALITY_virtual, getVirtuality("DW_VIRTUALITY_virtual")); + EXPECT_EQ(DW_VIRTUALITY_pure_virtual, + getVirtuality("DW_VIRTUALITY_pure_virtual")); + + // Invalid strings. + EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("DW_VIRTUALITY_invalid")); + EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("DW_VIRTUALITY_max")); + EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("something else")); +} + +} // end namespace diff --git a/unittests/Support/EndianStreamTest.cpp b/unittests/Support/EndianStreamTest.cpp new file mode 100644 index 0000000000000..6a69be55f9266 --- /dev/null +++ b/unittests/Support/EndianStreamTest.cpp @@ -0,0 +1,157 @@ +//===- unittests/Support/EndianStreamTest.cpp - EndianStream.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/ADT/SmallString.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/DataTypes.h" +#include "gtest/gtest.h" +using namespace llvm; +using namespace support; + +namespace { + +TEST(EndianStream, WriteInt32LE) { + SmallString<16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<little> LE(OS); + LE.write(static_cast<int32_t>(-1362446643)); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xCD); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xB6); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xCA); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xAE); +} + +TEST(EndianStream, WriteInt32BE) { + SmallVector<char, 16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<big> BE(OS); + BE.write(static_cast<int32_t>(-1362446643)); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xAE); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xCA); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xB6); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xCD); +} + + +TEST(EndianStream, WriteFloatLE) { + SmallString<16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<little> LE(OS); + LE.write(12345.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); +} + +TEST(EndianStream, WriteFloatBE) { + SmallVector<char, 16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<big> BE(OS); + BE.write(12345.0f); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0x46); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x40); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xE4); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x00); +} + +TEST(EndianStream, WriteInt64LE) { + SmallString<16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<little> LE(OS); + LE.write(static_cast<int64_t>(-136244664332342323)); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xCD); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xAB); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xED); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x1B); + EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x33); + EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xF6); + EXPECT_EQ(static_cast<uint8_t>(data[6]), 0x1B); + EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xFE); +} + +TEST(EndianStream, WriteInt64BE) { + SmallVector<char, 16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<big> BE(OS); + BE.write(static_cast<int64_t>(-136244664332342323)); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xFE); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x1B); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xF6); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x33); + EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x1B); + EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xED); + EXPECT_EQ(static_cast<uint8_t>(data[6]), 0xAB); + EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xCD); +} + +TEST(EndianStream, WriteDoubleLE) { + SmallString<16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<little> LE(OS); + LE.write(-2349214918.58107); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0x20); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x98); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xD2); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x98); + EXPECT_EQ(static_cast<uint8_t>(data[4]), 0xC5); + EXPECT_EQ(static_cast<uint8_t>(data[5]), 0x80); + EXPECT_EQ(static_cast<uint8_t>(data[6]), 0xE1); + EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xC1); +} + +TEST(EndianStream, WriteDoubleBE) { + SmallVector<char, 16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<big> BE(OS); + BE.write(-2349214918.58107); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xC1); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xE1); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0x80); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xC5); + EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x98); + EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xD2); + EXPECT_EQ(static_cast<uint8_t>(data[6]), 0x98); + EXPECT_EQ(static_cast<uint8_t>(data[7]), 0x20); +} + + +} // end anon namespace diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index 82bbe090960ac..5e8d442a70394 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -66,6 +66,11 @@ TEST(ErrorOr, Covariant) { ErrorOr<std::unique_ptr<int>> b4(b3); } +TEST(ErrorOr, Comparison) { + ErrorOr<int> x(std::errc::no_such_file_or_directory); + EXPECT_EQ(x, std::errc::no_such_file_or_directory); +} + // ErrorOr<int*> x(nullptr); // ErrorOr<std::unique_ptr<int>> y = x; // invalid conversion static_assert( diff --git a/unittests/Support/Makefile b/unittests/Support/Makefile index 9c0a7f94d7725..21657f12e3dc1 100644 --- a/unittests/Support/Makefile +++ b/unittests/Support/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = Support -LINK_COMPONENTS := core 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 93a38cb03fd93..5c95b500dd4c8 100644 --- a/unittests/Support/MathExtrasTest.cpp +++ b/unittests/Support/MathExtrasTest.cpp @@ -141,21 +141,18 @@ TEST(MathExtras, ByteSwap_64) { EXPECT_EQ(0x1100FFEEDDCCBBAAULL, ByteSwap_64(0xAABBCCDDEEFF0011LL)); } -TEST(MathExtras, CountLeadingOnes_32) { +TEST(MathExtras, countLeadingOnes) { for (int i = 30; i >= 0; --i) { // Start with all ones and unset some bit. - EXPECT_EQ(31u - i, CountLeadingOnes_32(0xFFFFFFFF ^ (1 << i))); + EXPECT_EQ(31u - i, countLeadingOnes(0xFFFFFFFF ^ (1 << i))); } -} - -TEST(MathExtras, CountLeadingOnes_64) { for (int i = 62; i >= 0; --i) { // Start with all ones and unset some bit. - EXPECT_EQ(63u - i, CountLeadingOnes_64(0xFFFFFFFFFFFFFFFFLL ^ (1LL << i))); + EXPECT_EQ(63u - i, countLeadingOnes(0xFFFFFFFFFFFFFFFFULL ^ (1LL << i))); } for (int i = 30; i >= 0; --i) { // Start with all ones and unset some bit. - EXPECT_EQ(31u - i, CountLeadingOnes_32(0xFFFFFFFF ^ (1 << i))); + EXPECT_EQ(31u - i, countLeadingOnes(0xFFFFFFFF ^ (1 << i))); } } diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 1cdd6adbf8ba3..ffb809aa207b2 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -26,7 +26,7 @@ protected: : data("this is some data") { } - virtual void SetUp() { } + void SetUp() override {} /// Common testing for different modes of getOpenFileSlice. /// Creates a temporary file with known contents, and uses diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 0d661c8ae6c00..262d27260ce43 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -168,6 +168,26 @@ TEST(Support, RelativePathIterator) { } } +TEST(Support, RelativePathDotIterator) { + SmallString<64> Path(StringRef(".c/.d/../.")); + typedef SmallVector<StringRef, 4> PathComponents; + PathComponents ExpectedPathComponents; + PathComponents ActualPathComponents; + + StringRef(Path).split(ExpectedPathComponents, "/"); + + for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E; + ++I) { + ActualPathComponents.push_back(*I); + } + + ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size()); + + for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) { + EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str()); + } +} + TEST(Support, AbsolutePathIterator) { SmallString<64> Path(StringRef("/c/d/e/foo.txt")); typedef SmallVector<StringRef, 4> PathComponents; @@ -191,6 +211,29 @@ TEST(Support, AbsolutePathIterator) { } } +TEST(Support, AbsolutePathDotIterator) { + SmallString<64> Path(StringRef("/.c/.d/../.")); + typedef SmallVector<StringRef, 4> PathComponents; + PathComponents ExpectedPathComponents; + PathComponents ActualPathComponents; + + StringRef(Path).split(ExpectedPathComponents, "/"); + + // The root path will also be a component when iterating + ExpectedPathComponents[0] = "/"; + + for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E; + ++I) { + ActualPathComponents.push_back(*I); + } + + ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size()); + + for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) { + EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str()); + } +} + #ifdef LLVM_ON_WIN32 TEST(Support, AbsolutePathIteratorWin32) { SmallString<64> Path(StringRef("c:\\c\\e\\foo.txt")); @@ -265,7 +308,7 @@ protected: /// be placed. It is removed at the end of each test (must be empty). SmallString<128> TestDirectory; - virtual void SetUp() { + void SetUp() override { ASSERT_NO_ERROR( fs::createUniqueDirectory("file-system-test", TestDirectory)); // We don't care about this specific file. @@ -273,9 +316,7 @@ protected: errs().flush(); } - virtual void TearDown() { - ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); - } + void TearDown() override { ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } }; TEST_F(FileSystemTest, Unique) { @@ -557,6 +598,7 @@ const char macho_dynamically_linked_shared_lib[] = 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"; 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"; @@ -587,6 +629,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(macho_bundle), DEFINE(macho_dynamically_linked_shared_lib_stub), DEFINE(macho_dsym_companion), + DEFINE(macho_kext_bundle), DEFINE(windows_resource) #undef DEFINE }; diff --git a/unittests/Support/ScaledNumberTest.cpp b/unittests/Support/ScaledNumberTest.cpp index d8d6e310ff9fc..2f38b2a40fb8f 100644 --- a/unittests/Support/ScaledNumberTest.cpp +++ b/unittests/Support/ScaledNumberTest.cpp @@ -155,7 +155,7 @@ TEST(ScaledNumberHelpersTest, getQuotient) { EXPECT_EQ(SP32(0xaaaaaaab, -33), getQuotient32(1, 3)); EXPECT_EQ(SP32(0xd5555555, -31), getQuotient32(5, 3)); - // 64-bit division is hard to test, since divide64 doesn't canonicalized its + // 64-bit division is hard to test, since divide64 doesn't canonicalize its // output. However, this is the algorithm the implementation uses: // // - Shift divisor right. @@ -532,4 +532,33 @@ TEST(ScaledNumberHelpersTest, getDifference) { EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, -1)); } +TEST(ScaledNumberHelpersTest, arithmeticOperators) { + EXPECT_EQ(ScaledNumber<uint32_t>(10, 0), + ScaledNumber<uint32_t>(1, 3) + ScaledNumber<uint32_t>(1, 1)); + EXPECT_EQ(ScaledNumber<uint32_t>(6, 0), + ScaledNumber<uint32_t>(1, 3) - ScaledNumber<uint32_t>(1, 1)); + EXPECT_EQ(ScaledNumber<uint32_t>(2, 3), + ScaledNumber<uint32_t>(1, 3) * ScaledNumber<uint32_t>(1, 1)); + EXPECT_EQ(ScaledNumber<uint32_t>(1, 2), + ScaledNumber<uint32_t>(1, 3) / ScaledNumber<uint32_t>(1, 1)); + EXPECT_EQ(ScaledNumber<uint32_t>(1, 2), ScaledNumber<uint32_t>(1, 3) >> 1); + EXPECT_EQ(ScaledNumber<uint32_t>(1, 4), ScaledNumber<uint32_t>(1, 3) << 1); + + EXPECT_EQ(ScaledNumber<uint64_t>(10, 0), + ScaledNumber<uint64_t>(1, 3) + ScaledNumber<uint64_t>(1, 1)); + EXPECT_EQ(ScaledNumber<uint64_t>(6, 0), + ScaledNumber<uint64_t>(1, 3) - ScaledNumber<uint64_t>(1, 1)); + EXPECT_EQ(ScaledNumber<uint64_t>(2, 3), + ScaledNumber<uint64_t>(1, 3) * ScaledNumber<uint64_t>(1, 1)); + EXPECT_EQ(ScaledNumber<uint64_t>(1, 2), + ScaledNumber<uint64_t>(1, 3) / ScaledNumber<uint64_t>(1, 1)); + EXPECT_EQ(ScaledNumber<uint64_t>(1, 2), ScaledNumber<uint64_t>(1, 3) >> 1); + EXPECT_EQ(ScaledNumber<uint64_t>(1, 4), ScaledNumber<uint64_t>(1, 3) << 1); +} + +TEST(ScaledNumberHelpersTest, toIntBug) { + ScaledNumber<uint32_t> n(1, 0); + EXPECT_EQ(1u, (n * n).toInt<uint32_t>()); +} + } // end namespace diff --git a/unittests/Support/SpecialCaseListTest.cpp b/unittests/Support/SpecialCaseListTest.cpp index 740dbfef40447..0657f8003e8be 100644 --- a/unittests/Support/SpecialCaseListTest.cpp +++ b/unittests/Support/SpecialCaseListTest.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SpecialCaseList.h" #include "gtest/gtest.h" @@ -30,6 +31,16 @@ protected: assert(Error == ""); return SCL; } + + std::string makeSpecialCaseListFile(StringRef Contents) { + int FD; + SmallString<64> Path; + sys::fs::createTemporaryFile("SpecialCaseListTest", "temp", FD, Path); + raw_fd_ostream OF(FD, true, true); + OF << Contents; + OF.close(); + return Path.str(); + } }; TEST_F(SpecialCaseListTest, Basic) { @@ -86,17 +97,18 @@ TEST_F(SpecialCaseListTest, Substring) { TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { std::string Error; EXPECT_EQ(nullptr, makeSpecialCaseList("badline", Error)); - EXPECT_EQ("Malformed line 1: 'badline'", Error); + EXPECT_EQ("malformed line 1: 'badline'", Error); EXPECT_EQ(nullptr, makeSpecialCaseList("src:bad[a-", Error)); - EXPECT_EQ("Malformed regex in line 1: 'bad[a-': invalid character range", + EXPECT_EQ("malformed regex in line 1: 'bad[a-': invalid character range", Error); EXPECT_EQ(nullptr, makeSpecialCaseList("src:a.c\n" "fun:fun(a\n", Error)); - EXPECT_EQ("Malformed regex in line 2: 'fun(a': parentheses not balanced", + EXPECT_EQ("malformed regex in line 2: 'fun(a': parentheses not balanced", Error); - EXPECT_EQ(nullptr, SpecialCaseList::create("unexisting", Error)); - EXPECT_EQ(0U, Error.find("Can't open file 'unexisting':")); + std::vector<std::string> Files(1, "unexisting"); + EXPECT_EQ(nullptr, SpecialCaseList::create(Files, Error)); + EXPECT_EQ(0U, Error.find("can't open file 'unexisting':")); } TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { @@ -104,6 +116,20 @@ TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { EXPECT_FALSE(SCL->inSection("foo", "bar")); } +TEST_F(SpecialCaseListTest, MultipleBlacklists) { + std::vector<std::string> Files; + Files.push_back(makeSpecialCaseListFile("src:bar\n" + "src:*foo*\n" + "src:ban=init\n")); + Files.push_back(makeSpecialCaseListFile("src:baz\n" + "src:*fog*\n")); + auto SCL = SpecialCaseList::createOrDie(Files); + EXPECT_TRUE(SCL->inSection("src", "bar")); + EXPECT_TRUE(SCL->inSection("src", "baz")); + EXPECT_FALSE(SCL->inSection("src", "ban")); + EXPECT_TRUE(SCL->inSection("src", "ban", "init")); + EXPECT_TRUE(SCL->inSection("src", "tomfoolery")); + EXPECT_TRUE(SCL->inSection("src", "tomfoglery")); } - +} diff --git a/unittests/Support/StreamingMemoryObject.cpp b/unittests/Support/StreamingMemoryObject.cpp index 20136491ab8bd..c043efbb5e473 100644 --- a/unittests/Support/StreamingMemoryObject.cpp +++ b/unittests/Support/StreamingMemoryObject.cpp @@ -27,3 +27,12 @@ TEST(StreamingMemoryObject, Test) { StreamingMemoryObject O(DS); EXPECT_TRUE(O.isValidAddress(32 * 1024)); } + +TEST(StreamingMemoryObject, TestSetKnownObjectSize) { + auto *DS = new NullDataStreamer(); + StreamingMemoryObject O(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/SwapByteOrderTest.cpp b/unittests/Support/SwapByteOrderTest.cpp index 525cfc1aea82c..4f2537c4d5dee 100644 --- a/unittests/Support/SwapByteOrderTest.cpp +++ b/unittests/Support/SwapByteOrderTest.cpp @@ -125,6 +125,19 @@ TEST(getSwappedBytes, int64_t) { sys::getSwappedBytes(int64_t(0x8877665544332211LL))); } +TEST(getSwappedBytes, float) { + EXPECT_EQ(1.79366203433576585078237386661e-43f, sys::getSwappedBytes(-0.0f)); + // 0x11223344 + EXPECT_EQ(7.1653228759765625e2f, sys::getSwappedBytes(1.2795344e-28f)); +} + +TEST(getSwappedBytes, double) { + EXPECT_EQ(6.32404026676795576546008054871e-322, sys::getSwappedBytes(-0.0)); + // 0x1122334455667788 + EXPECT_EQ(-7.08687663657301358331704585496e-268, + sys::getSwappedBytes(3.84141202447173065923064450234e-226)); +} + TEST(swapByteOrder, uint8_t) { uint8_t value = 0x11; sys::swapByteOrder(value); @@ -173,4 +186,16 @@ TEST(swapByteOrder, int64_t) { EXPECT_EQ(int64_t(0x1122334455667788LL), value); } +TEST(swapByteOrder, float) { + float value = 7.1653228759765625e2f; // 0x44332211 + sys::swapByteOrder(value); + EXPECT_EQ(1.2795344e-28f, value); +} + +TEST(swapByteOrder, double) { + double value = -7.08687663657301358331704585496e-268; // 0x8877665544332211 + sys::swapByteOrder(value); + EXPECT_EQ(3.84141202447173065923064450234e-226, value); +} + } diff --git a/unittests/Support/TargetRegistry.cpp b/unittests/Support/TargetRegistry.cpp new file mode 100644 index 0000000000000..ae89c8b649303 --- /dev/null +++ b/unittests/Support/TargetRegistry.cpp @@ -0,0 +1,42 @@ +//===- 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/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 074e27f8318dc..7248124992b4d 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -46,6 +46,9 @@ typedef std::vector<FooBar> FooBarSequence; LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar) +struct FooBarContainer { + FooBarSequence fbs; +}; namespace llvm { namespace yaml { @@ -56,6 +59,12 @@ namespace yaml { io.mapRequired("bar", fb.bar); } }; + + template <> struct MappingTraits<FooBarContainer> { + static void mapping(IO &io, FooBarContainer &fb) { + io.mapRequired("fbs", fb.fbs); + } + }; } } @@ -109,6 +118,83 @@ TEST(YAMLIO, TestSequenceMapRead) { EXPECT_EQ(map2.bar, 9); } +// +// Test the reading of a map containing a yaml sequence of mappings +// +TEST(YAMLIO, TestContainerSequenceMapRead) { + { + FooBarContainer cont; + Input yin2("---\nfbs:\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n"); + yin2 >> cont; + + EXPECT_FALSE(yin2.error()); + EXPECT_EQ(cont.fbs.size(), 2UL); + EXPECT_EQ(cont.fbs[0].foo, 3); + EXPECT_EQ(cont.fbs[0].bar, 5); + EXPECT_EQ(cont.fbs[1].foo, 7); + EXPECT_EQ(cont.fbs[1].bar, 9); + } + + { + FooBarContainer cont; + Input yin("---\nfbs:\n...\n"); + yin >> cont; + // Okay: Empty node represents an empty array. + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } + + { + FooBarContainer cont; + Input yin("---\nfbs: !!null null\n...\n"); + yin >> cont; + // Okay: null represents an empty array. + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } + + { + FooBarContainer cont; + Input yin("---\nfbs: ~\n...\n"); + yin >> cont; + // Okay: null represents an empty array. + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } + + { + FooBarContainer cont; + Input yin("---\nfbs: null\n...\n"); + yin >> cont; + // Okay: null represents an empty array. + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } +} + +// +// Test the reading of a map containing a malformed yaml sequence +// +TEST(YAMLIO, TestMalformedContainerSequenceMapRead) { + { + FooBarContainer cont; + Input yin("---\nfbs:\n foo: 3\n bar: 5\n...\n", nullptr, + suppressErrorMessages); + yin >> cont; + // Error: fbs is not a sequence. + EXPECT_TRUE(!!yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } + + { + FooBarContainer cont; + Input yin("---\nfbs: 'scalar'\n...\n", nullptr, suppressErrorMessages); + yin >> cont; + // This should be an error. + EXPECT_TRUE(!!yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } +} // // Test writing then reading back a sequence of mappings @@ -694,6 +780,146 @@ TEST(YAMLIO, TestReadWriteMyCustomType) { //===----------------------------------------------------------------------===// +// Test BlockScalarTraits +//===----------------------------------------------------------------------===// + +struct MultilineStringType { + std::string str; +}; + +struct MultilineStringTypeMap { + MultilineStringType name; + MultilineStringType description; + MultilineStringType ingredients; + MultilineStringType recipes; + MultilineStringType warningLabels; + MultilineStringType documentation; + int price; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<MultilineStringTypeMap> { + static void mapping(IO &io, MultilineStringTypeMap& s) { + io.mapRequired("name", s.name); + io.mapRequired("description", s.description); + io.mapRequired("ingredients", s.ingredients); + io.mapRequired("recipes", s.recipes); + io.mapRequired("warningLabels", s.warningLabels); + io.mapRequired("documentation", s.documentation); + io.mapRequired("price", s.price); + } + }; + + // MultilineStringType is formatted as a yaml block literal scalar. A value of + // "Hello\nWorld" would be represented in yaml as + // | + // Hello + // World + template <> + struct BlockScalarTraits<MultilineStringType> { + static void output(const MultilineStringType &value, void *ctxt, + llvm::raw_ostream &out) { + out << value.str; + } + static StringRef input(StringRef scalar, void *ctxt, + MultilineStringType &value) { + value.str = scalar.str(); + return StringRef(); + } + }; +} +} + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType) + +// +// Test writing then reading back custom values +// +TEST(YAMLIO, TestReadWriteMultilineStringType) { + std::string intermediate; + { + MultilineStringTypeMap map; + map.name.str = "An Item"; + map.description.str = "Hello\nWorld"; + map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n"; + map.recipes.str = "\n\nTest 1\n\n\n"; + map.warningLabels.str = ""; + map.documentation.str = "\n\n"; + map.price = 350; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + } + { + Input yin(intermediate); + MultilineStringTypeMap map2; + yin >> map2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(map2.name.str, "An Item\n"); + EXPECT_EQ(map2.description.str, "Hello\nWorld\n"); + EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n"); + EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n"); + EXPECT_TRUE(map2.warningLabels.str.empty()); + EXPECT_TRUE(map2.documentation.str.empty()); + EXPECT_EQ(map2.price, 350); + } +} + +// +// Test writing then reading back custom values +// +TEST(YAMLIO, TestReadWriteBlockScalarDocuments) { + std::string intermediate; + { + std::vector<MultilineStringType> documents; + MultilineStringType doc; + doc.str = "Hello\nWorld"; + documents.push_back(doc); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << documents; + + // Verify that the block scalar header was written out on the same line + // as the document marker. + EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |")); + } + { + Input yin(intermediate); + std::vector<MultilineStringType> documents2; + yin >> documents2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(documents2.size(), size_t(1)); + EXPECT_EQ(documents2[0].str, "Hello\nWorld\n"); + } +} + +TEST(YAMLIO, TestReadWriteBlockScalarValue) { + std::string intermediate; + { + MultilineStringType doc; + doc.str = "Just a block\nscalar doc"; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << doc; + } + { + Input yin(intermediate); + MultilineStringType doc; + yin >> doc; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(doc.str, "Just a block\nscalar doc\n"); + } +} + +//===----------------------------------------------------------------------===// // Test flow sequences //===----------------------------------------------------------------------===// @@ -743,6 +969,26 @@ namespace yaml { } } +typedef std::vector<MyNumber> MyNumberFlowSequence; + +LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence) + +struct NameAndNumbersFlow { + llvm::StringRef name; + std::vector<MyNumberFlowSequence> sequenceOfNumbers; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<NameAndNumbersFlow> { + static void mapping(IO &io, NameAndNumbersFlow& nn) { + io.mapRequired("name", nn.name); + io.mapRequired("sequenceOfNumbers", nn.sequenceOfNumbers); + } + }; +} +} // // Test writing then reading back custom values @@ -790,6 +1036,51 @@ TEST(YAMLIO, TestReadWriteMyFlowSequence) { } +// +// Test writing then reading back a sequence of flow sequences. +// +TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) { + std::string intermediate; + { + NameAndNumbersFlow map; + map.name = "hello"; + MyNumberFlowSequence single = { 0 }; + MyNumberFlowSequence numbers = { 12, 1, -512 }; + map.sequenceOfNumbers.push_back(single); + map.sequenceOfNumbers.push_back(numbers); + map.sequenceOfNumbers.push_back(MyNumberFlowSequence()); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + + // Verify sequences were written in flow style + // and that the parent sequence used '-'. + ostr.flush(); + llvm::StringRef flowOut(intermediate); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ ]")); + } + + { + Input yin(intermediate); + NameAndNumbersFlow map2; + yin >> map2; + + EXPECT_FALSE(yin.error()); + EXPECT_TRUE(map2.name.equals("hello")); + EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL); + EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL); + EXPECT_EQ(0, map2.sequenceOfNumbers[0][0]); + EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL); + EXPECT_EQ(12, map2.sequenceOfNumbers[1][0]); + EXPECT_EQ(1, map2.sequenceOfNumbers[1][1]); + EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]); + EXPECT_TRUE(map2.sequenceOfNumbers[2].empty()); + } +} + //===----------------------------------------------------------------------===// // Test normalizing/denormalizing //===----------------------------------------------------------------------===// @@ -1216,6 +1507,91 @@ TEST(YAMLIO, TestValidatingInput) { EXPECT_TRUE(!!yin.error()); } +//===----------------------------------------------------------------------===// +// Test flow mapping +//===----------------------------------------------------------------------===// + +struct FlowFooBar { + int foo; + int bar; + + FlowFooBar() : foo(0), bar(0) {} + FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {} +}; + +typedef std::vector<FlowFooBar> FlowFooBarSequence; + +LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar) + +struct FlowFooBarDoc { + FlowFooBar attribute; + FlowFooBarSequence seq; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<FlowFooBar> { + static void mapping(IO &io, FlowFooBar &fb) { + io.mapRequired("foo", fb.foo); + io.mapRequired("bar", fb.bar); + } + + static const bool flow = true; + }; + + template <> + struct MappingTraits<FlowFooBarDoc> { + static void mapping(IO &io, FlowFooBarDoc &fb) { + io.mapRequired("attribute", fb.attribute); + io.mapRequired("seq", fb.seq); + } + }; +} +} + +// +// Test writing then reading back custom mappings +// +TEST(YAMLIO, TestReadWriteMyFlowMapping) { + std::string intermediate; + { + FlowFooBarDoc doc; + doc.attribute = FlowFooBar(42, 907); + doc.seq.push_back(FlowFooBar(1, 2)); + doc.seq.push_back(FlowFooBar(0, 0)); + doc.seq.push_back(FlowFooBar(-1, 1024)); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << doc; + + // Verify that mappings were written in flow style + ostr.flush(); + llvm::StringRef flowOut(intermediate); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }")); + } + + { + Input yin(intermediate); + FlowFooBarDoc doc2; + yin >> doc2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(doc2.attribute.foo, 42); + EXPECT_EQ(doc2.attribute.bar, 907); + EXPECT_EQ(doc2.seq.size(), 3UL); + EXPECT_EQ(doc2.seq[0].foo, 1); + EXPECT_EQ(doc2.seq[0].bar, 2); + EXPECT_EQ(doc2.seq[1].foo, 0); + EXPECT_EQ(doc2.seq[1].bar, 0); + EXPECT_EQ(doc2.seq[2].foo, -1); + EXPECT_EQ(doc2.seq[2].bar, 1024); + } +} //===----------------------------------------------------------------------===// // Test error handling diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp index 823a0d6e3e03e..69b354a91d11e 100644 --- a/unittests/Support/YAMLParserTest.cpp +++ b/unittests/Support/YAMLParserTest.cpp @@ -130,6 +130,45 @@ TEST(YAMLParser, ParsesArrayOfArrays) { ExpectParseSuccess("Array of arrays", "[[]]"); } +TEST(YAMLParser, ParsesBlockLiteralScalars) { + ExpectParseSuccess("Block literal scalar", "test: |\n Hello\n World\n"); + ExpectParseSuccess("Block literal scalar EOF", "test: |\n Hello\n World"); + ExpectParseSuccess("Empty block literal scalar header EOF", "test: | "); + ExpectParseSuccess("Empty block literal scalar", "test: |\ntest2: 20"); + ExpectParseSuccess("Empty block literal scalar 2", "- | \n \n\n \n- 42"); + ExpectParseSuccess("Block literal scalar in sequence", + "- |\n Testing\n Out\n\n- 22"); + ExpectParseSuccess("Block literal scalar in document", + "--- |\n Document\n..."); + ExpectParseSuccess("Empty non indented lines still count", + "- |\n First line\n \n\n Another line\n\n- 2"); + ExpectParseSuccess("Comment in block literal scalar header", + "test: | # Comment \n No Comment\ntest 2: | # Void"); + ExpectParseSuccess("Chomping indicators in block literal scalar header", + "test: |- \n Hello\n\ntest 2: |+ \n\n World\n\n\n"); + ExpectParseSuccess("Indent indicators in block literal scalar header", + "test: |1 \n \n Hello \n World\n"); + ExpectParseSuccess("Chomping and indent indicators in block literals", + "test: |-1\n Hello\ntest 2: |9+\n World"); + ExpectParseSuccess("Trailing comments in block literals", + "test: |\n Content\n # Trailing\n #Comment\ntest 2: 3"); + ExpectParseError("Invalid block scalar header", "test: | failure"); + ExpectParseError("Invalid line indentation", "test: |\n First line\n Error"); + ExpectParseError("Long leading space line", "test: |\n \n Test\n"); +} + +TEST(YAMLParser, NullTerminatedBlockScalars) { + SourceMgr SM; + yaml::Stream Stream("test: |\n Hello\n World\n", SM); + yaml::Document &Doc = *Stream.begin(); + yaml::MappingNode *Map = cast<yaml::MappingNode>(Doc.getRoot()); + StringRef Value = + cast<yaml::BlockScalarNode>(Map->begin()->getValue())->getValue(); + + EXPECT_EQ(Value, "Hello\nWorld\n"); + EXPECT_EQ(Value.data()[Value.size()], '\0'); +} + TEST(YAMLParser, HandlesEndOfFileGracefully) { ExpectParseError("In string starting with EOF", "[\""); ExpectParseError("In string hitting EOF", "[\" "); @@ -141,6 +180,10 @@ TEST(YAMLParser, HandlesEndOfFileGracefully) { ExpectParseError("In object hitting EOF", "{\"\""); } +TEST(YAMLParser, HandlesNullValuesInKeyValueNodesGracefully) { + ExpectParseError("KeyValueNode with null value", "test: '"); +} + // Checks that the given string can be parsed into an identical string inside // of an array. static void ExpectCanParseString(StringRef String) { diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index 39cfaf004c72b..ff986025b2ccb 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -162,6 +162,8 @@ TEST(raw_ostreamTest, FormatHex) { EXPECT_EQ("0x1", printToString(format_hex(1, 3), 3)); EXPECT_EQ("0x12", printToString(format_hex(0x12, 3), 4)); EXPECT_EQ("0x123", printToString(format_hex(0x123, 3), 5)); + EXPECT_EQ("FF", printToString(format_hex_no_prefix(0xFF, 2, true), 4)); + EXPECT_EQ("ABCD", printToString(format_hex_no_prefix(0xABCD, 2, true), 4)); EXPECT_EQ("0xffffffffffffffff", printToString(format_hex(UINT64_MAX, 18), 18)); EXPECT_EQ("0x8000000000000000", diff --git a/unittests/Support/raw_pwrite_stream_test.cpp b/unittests/Support/raw_pwrite_stream_test.cpp new file mode 100644 index 0000000000000..a62f6bacb0703 --- /dev/null +++ b/unittests/Support/raw_pwrite_stream_test.cpp @@ -0,0 +1,64 @@ +//===- raw_pwrite_stream_test.cpp - raw_pwrite_stream 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/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { + +TEST(raw_pwrite_ostreamTest, TestSVector) { + SmallVector<char, 0> Buffer; + raw_svector_ostream OS(Buffer); + OS << "abcd"; + StringRef Test = "test"; + OS.pwrite(Test.data(), Test.size(), 0); + EXPECT_EQ(Test, OS.str()); + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG + EXPECT_DEATH(OS.pwrite("12345", 5, 0), + "We don't support extending the stream"); +#endif +#endif +} + +TEST(raw_pwrite_ostreamTest, TestFD) { + SmallString<64> Path; + int FD; + sys::fs::createTemporaryFile("foo", "bar", FD, Path); + raw_fd_ostream OS(FD, true); + OS << "abcd"; + StringRef Test = "test"; + OS.pwrite(Test.data(), Test.size(), 0); + OS.pwrite(Test.data(), Test.size(), 0); + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG + EXPECT_DEATH(OS.pwrite("12345", 5, 0), + "We don't support extending the stream"); +#endif +#endif +} + +#ifdef LLVM_ON_UNIX +TEST(raw_pwrite_ostreamTest, TestDevNull) { + int FD; + sys::fs::openFileForWrite("/dev/null", FD, sys::fs::F_None); + raw_fd_ostream OS(FD, true); + OS << "abcd"; + StringRef Test = "test"; + OS.pwrite(Test.data(), Test.size(), 0); + OS.pwrite(Test.data(), Test.size(), 0); +} +#endif +} |