diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
commit | 67c32a98315f785a9ec9d531c1f571a0196c7463 (patch) | |
tree | 4abb9cbeecc7901726dd0b4a37369596c852e9ef /unittests/Support | |
parent | 9f61947910e6ab40de38e6b4034751ef1513200f (diff) |
Diffstat (limited to 'unittests/Support')
26 files changed, 713 insertions, 185 deletions
diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index 0fc84c7613f3..7f15776d6f00 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -17,9 +17,9 @@ namespace { TEST(AllocatorTest, Basics) { BumpPtrAllocator Alloc; - int *a = (int*)Alloc.Allocate(sizeof(int), 0); - int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 0); - int *c = (int*)Alloc.Allocate(sizeof(int), 0); + int *a = (int*)Alloc.Allocate(sizeof(int), 1); + int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 1); + int *c = (int*)Alloc.Allocate(sizeof(int), 1); *a = 1; b[0] = 2; b[9] = 2; @@ -49,11 +49,11 @@ TEST(AllocatorTest, Basics) { // Allocate enough bytes to create three slabs. TEST(AllocatorTest, ThreeSlabs) { BumpPtrAllocator Alloc; - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(3U, Alloc.GetNumSlabs()); } @@ -61,15 +61,15 @@ TEST(AllocatorTest, ThreeSlabs) { // again. TEST(AllocatorTest, TestReset) { BumpPtrAllocator Alloc; - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); Alloc.Reset(); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -99,11 +99,11 @@ TEST(AllocatorTest, TestOverflow) { BumpPtrAllocator Alloc; // Fill the slab right up until the end pointer. - Alloc.Allocate(4096, 0); + Alloc.Allocate(4096, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); // If we don't allocate a new slab, then we will have overflowed. - Alloc.Allocate(1, 0); + Alloc.Allocate(1, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -111,7 +111,20 @@ TEST(AllocatorTest, TestOverflow) { TEST(AllocatorTest, TestSmallSlabSize) { BumpPtrAllocator Alloc; - Alloc.Allocate(8000, 0); + Alloc.Allocate(8000, 1); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); +} + +// Test requesting alignment that goes past the end of the current slab. +TEST(AllocatorTest, TestAlignmentPastSlab) { + BumpPtrAllocator Alloc; + Alloc.Allocate(4095, 1); + + // Aligning the current slab pointer is likely to move it past the end of the + // slab, which would confuse any unsigned comparisons with the difference of + // the the end pointer and the aligned pointer. + Alloc.Allocate(1024, 8192); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -130,7 +143,7 @@ public: void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*)); // Find the slab start. - void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment); + void *Slab = (void *)alignAddr((char*)MemBase + sizeof(void *), Alignment); // Hold a pointer to the base so we can free the whole malloced block. ((void**)Slab)[-1] = MemBase; @@ -155,7 +168,7 @@ TEST(AllocatorTest, TestBigAlignment) { BumpPtrAllocatorImpl<MockSlabAllocator> Alloc; // First allocate a tiny bit to ensure we have to re-align things. - (void)Alloc.Allocate(1, 0); + (void)Alloc.Allocate(1, 1); // Now the big chunk with a big alignment. (void)Alloc.Allocate(3000, 2048); diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 97c5c43aeb6e..dd270ccea42d 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -32,6 +32,7 @@ add_llvm_unittest(SupportTests ScaledNumberTest.cpp SourceMgrTest.cpp SpecialCaseListTest.cpp + StreamingMemoryObject.cpp StringPool.cpp SwapByteOrderTest.cpp ThreadLocalTest.cpp @@ -42,3 +43,8 @@ add_llvm_unittest(SupportTests formatted_raw_ostream_test.cpp raw_ostream_test.cpp ) + +# ManagedStatic.cpp uses <pthread>. +if(LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD) + target_link_libraries(SupportTests pthread) +endif() diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp index 88c7d19aa464..3218189eeab6 100644 --- a/unittests/Support/Casting.cpp +++ b/unittests/Support/Casting.cpp @@ -232,3 +232,99 @@ namespace TemporaryCast { struct pod {}; IllegalCast *testIllegalCast() { return cast<foo>(pod()); } } + +namespace { +namespace pointer_wrappers { + +struct Base { + bool IsDerived; + Base(bool IsDerived = false) : IsDerived(IsDerived) {} +}; + +struct Derived : Base { + Derived() : Base(true) {} + static bool classof(const Base *B) { return B->IsDerived; } +}; + +class PTy { + Base *B; +public: + PTy(Base *B) : B(B) {} + LLVM_EXPLICIT operator bool() const { return get(); } + Base *get() const { return B; } +}; + +} // end namespace pointer_wrappers +} // end namespace + +namespace llvm { + +template <> struct simplify_type<pointer_wrappers::PTy> { + typedef pointer_wrappers::Base *SimpleType; + static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) { + return P.get(); + } +}; +template <> struct simplify_type<const pointer_wrappers::PTy> { + typedef pointer_wrappers::Base *SimpleType; + static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) { + return P.get(); + } +}; + +} // end namespace llvm + +namespace { +namespace pointer_wrappers { + +// Some objects. +pointer_wrappers::Base B; +pointer_wrappers::Derived D; + +// Mutable "smart" pointers. +pointer_wrappers::PTy MN(nullptr); +pointer_wrappers::PTy MB(&B); +pointer_wrappers::PTy MD(&D); + +// Const "smart" pointers. +const pointer_wrappers::PTy CN(nullptr); +const pointer_wrappers::PTy CB(&B); +const pointer_wrappers::PTy CD(&D); + +TEST(CastingTest, smart_isa) { + EXPECT_TRUE(!isa<pointer_wrappers::Derived>(MB)); + EXPECT_TRUE(!isa<pointer_wrappers::Derived>(CB)); + EXPECT_TRUE(isa<pointer_wrappers::Derived>(MD)); + EXPECT_TRUE(isa<pointer_wrappers::Derived>(CD)); +} + +TEST(CastingTest, smart_cast) { + EXPECT_TRUE(cast<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(cast<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_cast_or_null) { + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MN) == nullptr); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CN) == nullptr); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_dyn_cast) { + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MB) == nullptr); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CB) == nullptr); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_dyn_cast_or_null) { + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MN) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CN) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MB) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CB) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CD) == &D); +} + +} // end namespace pointer_wrappers +} // end namespace diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index e4a1b67c47ea..ac8d3d8c9d63 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -153,14 +153,14 @@ class StrDupSaver : public cl::StringSaver { }; typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver, - SmallVectorImpl<const char *> &NewArgv); - + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs); void testCommandLineTokenizer(ParserFunction *parse, const char *Input, const char *const Output[], size_t OutputSize) { SmallVector<const char *, 0> Actual; StrDupSaver Saver; - parse(Input, Saver, Actual); + parse(Input, Saver, Actual, /*MarkEOLs=*/false); EXPECT_EQ(OutputSize, Actual.size()); for (unsigned I = 0, E = Actual.size(); I != E; ++I) { if (I < OutputSize) diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp index 698ae3aa2fc0..36b84d85f22b 100644 --- a/unittests/Support/CompressionTest.cpp +++ b/unittests/Support/CompressionTest.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Compression.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" #include "gtest/gtest.h" diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index 16c9bebfde16..49748db4ae97 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -10,8 +10,8 @@ #include "llvm/Support/ConvertUTF.h" #include "gtest/gtest.h" #include <string> -#include <vector> #include <utility> +#include <vector> using namespace llvm; @@ -39,30 +39,30 @@ TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) { TEST(ConvertUTFTest, OddLengthInput) { std::string Result; - bool Success = convertUTF16ToUTF8String(ArrayRef<char>("xxxxx", 5), Result); + bool Success = convertUTF16ToUTF8String(makeArrayRef("xxxxx", 5), Result); EXPECT_FALSE(Success); } TEST(ConvertUTFTest, Empty) { std::string Result; - bool Success = convertUTF16ToUTF8String(ArrayRef<char>(), Result); + bool Success = convertUTF16ToUTF8String(None, Result); EXPECT_TRUE(Success); EXPECT_TRUE(Result.empty()); } TEST(ConvertUTFTest, HasUTF16BOM) { - bool HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xff\xfe", 2)); + bool HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xff\xfe", 2)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff", 2)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff", 2)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff ", 3)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff ", 3)); EXPECT_TRUE(HasBOM); // Don't care about odd lengths. - HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff\x00asdf", 6)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff\x00asdf", 6)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>()); + HasBOM = hasUTF16ByteOrderMark(None); EXPECT_FALSE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe", 1)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe", 1)); EXPECT_FALSE(HasBOM); } @@ -141,8 +141,8 @@ CheckConvertUTF8ToUnicodeScalars(ConvertUTFResultContainer Expected, if (!Partial) std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsLenient(S); else - std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsPartialLenient(S); + if (Expected.ErrorCode != ErrorCode) return ::testing::AssertionFailure() << "Expected error code " << Expected.ErrorCode << ", actual " diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index d76e7d62421f..82bbe090960a 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -60,5 +60,36 @@ TEST(ErrorOr, Covariant) { ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(nullptr)); b1 = ErrorOr<std::unique_ptr<D> >(nullptr); + + ErrorOr<std::unique_ptr<int>> b2(ErrorOr<int *>(nullptr)); + ErrorOr<int *> b3(nullptr); + ErrorOr<std::unique_ptr<int>> b4(b3); } + +// ErrorOr<int*> x(nullptr); +// ErrorOr<std::unique_ptr<int>> y = x; // invalid conversion +static_assert( + !std::is_convertible<const ErrorOr<int *> &, + ErrorOr<std::unique_ptr<int>>>::value, + "do not invoke explicit ctors in implicit conversion from lvalue"); + +// ErrorOr<std::unique_ptr<int>> y = ErrorOr<int*>(nullptr); // invalid +// // conversion +static_assert( + !std::is_convertible<ErrorOr<int *> &&, + ErrorOr<std::unique_ptr<int>>>::value, + "do not invoke explicit ctors in implicit conversion from rvalue"); + +// ErrorOr<int*> x(nullptr); +// ErrorOr<std::unique_ptr<int>> y; +// y = x; // invalid conversion +static_assert(!std::is_assignable<ErrorOr<std::unique_ptr<int>>, + const ErrorOr<int *> &>::value, + "do not invoke explicit ctors in assignment"); + +// ErrorOr<std::unique_ptr<int>> x; +// x = ErrorOr<int*>(nullptr); // invalid conversion +static_assert(!std::is_assignable<ErrorOr<std::unique_ptr<int>>, + ErrorOr<int *> &&>::value, + "do not invoke explicit ctors in assignment"); } // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index b086f1e118d2..c7e10066b4ad 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -65,9 +66,8 @@ TEST(FileOutputBuffer, Test) { // Do *not* commit buffer. } // Verify file does not exist (because buffer not committed). - bool Exists = false; - ASSERT_NO_ERROR(fs::exists(Twine(File2), Exists)); - EXPECT_FALSE(Exists); + ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist), + errc::no_such_file_or_directory); ASSERT_NO_ERROR(fs::remove(File2.str())); // TEST 3: Verify sizing down case. @@ -80,14 +80,13 @@ TEST(FileOutputBuffer, Test) { memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); // Write to end of buffer to verify it is writable. memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20); - // Commit buffer, but size down to smaller size - ASSERT_NO_ERROR(Buffer->commit(5000)); + ASSERT_NO_ERROR(Buffer->commit()); } // Verify file is correct size. uint64_t File3Size; ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size)); - ASSERT_EQ(File3Size, 5000ULL); + ASSERT_EQ(File3Size, 8192000ULL); ASSERT_NO_ERROR(fs::remove(File3.str())); // TEST 4: Verify file can be made executable. diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp index b1ca13ef2416..76b63e5a8381 100644 --- a/unittests/Support/LEB128Test.cpp +++ b/unittests/Support/LEB128Test.cpp @@ -106,6 +106,7 @@ TEST(LEB128Test, DecodeULEB128) { EXPECT_DECODE_ULEB128_EQ(0xffu, "\xff\x01"); EXPECT_DECODE_ULEB128_EQ(0x100u, "\x80\x02"); EXPECT_DECODE_ULEB128_EQ(0x101u, "\x81\x02"); + EXPECT_DECODE_ULEB128_EQ(4294975616ULL, "\x80\xc1\x80\x80\x10"); // Decode ULEB128 with extra padding bytes EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x00"); @@ -118,6 +119,42 @@ TEST(LEB128Test, DecodeULEB128) { #undef EXPECT_DECODE_ULEB128_EQ } +TEST(LEB128Test, DecodeSLEB128) { +#define EXPECT_DECODE_SLEB128_EQ(EXPECTED, VALUE) \ + do { \ + unsigned ActualSize = 0; \ + int64_t Actual = decodeSLEB128(reinterpret_cast<const uint8_t *>(VALUE), \ + &ActualSize); \ + EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \ + EXPECT_EQ(EXPECTED, Actual); \ + } while (0) + + // Decode SLEB128 + EXPECT_DECODE_SLEB128_EQ(0L, "\x00"); + EXPECT_DECODE_SLEB128_EQ(1L, "\x01"); + EXPECT_DECODE_SLEB128_EQ(63L, "\x3f"); + EXPECT_DECODE_SLEB128_EQ(-64L, "\x40"); + EXPECT_DECODE_SLEB128_EQ(-63L, "\x41"); + EXPECT_DECODE_SLEB128_EQ(-1L, "\x7f"); + EXPECT_DECODE_SLEB128_EQ(128L, "\x80\x01"); + EXPECT_DECODE_SLEB128_EQ(129L, "\x81\x01"); + EXPECT_DECODE_SLEB128_EQ(-129L, "\xff\x7e"); + EXPECT_DECODE_SLEB128_EQ(-128L, "\x80\x7f"); + EXPECT_DECODE_SLEB128_EQ(-127L, "\x81\x7f"); + EXPECT_DECODE_SLEB128_EQ(64L, "\xc0\x00"); + EXPECT_DECODE_SLEB128_EQ(-12345L, "\xc7\x9f\x7f"); + + // Decode unnormalized SLEB128 with extra padding bytes. + EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x00"); + EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x00"); + EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x80\x00"); + +#undef EXPECT_DECODE_SLEB128_EQ +} + TEST(LEB128Test, SLEB128Size) { // Positive Value Testing Plan: // (1) 128 ^ n - 1 ........ need (n+1) bytes diff --git a/unittests/Support/LineIteratorTest.cpp b/unittests/Support/LineIteratorTest.cpp index 18f3fa99bcde..67f9d9777363 100644 --- a/unittests/Support/LineIteratorTest.cpp +++ b/unittests/Support/LineIteratorTest.cpp @@ -17,9 +17,9 @@ using namespace llvm::sys; namespace { TEST(LineIteratorTest, Basic) { - std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("line 1\n" - "line 2\n" - "line 3")); + std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "line 3"); line_iterator I = line_iterator(*Buffer), E; @@ -40,15 +40,17 @@ TEST(LineIteratorTest, Basic) { EXPECT_EQ(E, I); } -TEST(LineIteratorTest, CommentSkipping) { +TEST(LineIteratorTest, CommentAndBlankSkipping) { std::unique_ptr<MemoryBuffer> Buffer( MemoryBuffer::getMemBuffer("line 1\n" "line 2\n" "# Comment 1\n" - "line 4\n" + "\n" + "line 5\n" + "\n" "# Comment 2")); - line_iterator I = line_iterator(*Buffer, '#'), E; + line_iterator I = line_iterator(*Buffer, true, '#'), E; EXPECT_FALSE(I.is_at_eof()); EXPECT_NE(E, I); @@ -59,20 +61,57 @@ TEST(LineIteratorTest, CommentSkipping) { EXPECT_EQ("line 2", *I); EXPECT_EQ(2, I.line_number()); ++I; - EXPECT_EQ("line 4", *I); - EXPECT_EQ(4, I.line_number()); + EXPECT_EQ("line 5", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, CommentSkippingKeepBlanks) { + std::unique_ptr<MemoryBuffer> Buffer( + MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "# Comment 1\n" + "# Comment 2\n" + "\n" + "line 6\n" + "\n" + "# Comment 3")); + + line_iterator I = line_iterator(*Buffer, false, '#'), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("line 1", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("line 2", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + EXPECT_EQ("line 6", *I); + EXPECT_EQ(6, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(7, I.line_number()); ++I; EXPECT_TRUE(I.is_at_eof()); EXPECT_EQ(E, I); } + TEST(LineIteratorTest, BlankSkipping) { - std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("\n\n\n" - "line 1\n" - "\n\n\n" - "line 2\n" - "\n\n\n")); + std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("\n\n\n" + "line 1\n" + "\n\n\n" + "line 2\n" + "\n\n\n"); line_iterator I = line_iterator(*Buffer), E; @@ -90,26 +129,65 @@ TEST(LineIteratorTest, BlankSkipping) { EXPECT_EQ(E, I); } +TEST(LineIteratorTest, BlankKeeping) { + std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("\n\n" + "line 3\n" + "\n" + "line 5\n" + "\n\n"); + line_iterator I = line_iterator(*Buffer, false), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("line 3", *I); + EXPECT_EQ(3, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(4, I.line_number()); + ++I; + EXPECT_EQ("line 5", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(6, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(7, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + TEST(LineIteratorTest, EmptyBuffers) { - std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("")); + std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(""); EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); + EXPECT_TRUE(line_iterator(*Buffer, false).is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, false)); - Buffer.reset(MemoryBuffer::getMemBuffer("\n\n\n")); + Buffer = MemoryBuffer::getMemBuffer("\n\n\n"); EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); - Buffer.reset(MemoryBuffer::getMemBuffer("# foo\n" - "\n" - "# bar")); - EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); - EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); - - Buffer.reset(MemoryBuffer::getMemBuffer("\n" - "# baz\n" - "\n")); - EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); - EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); + Buffer = MemoryBuffer::getMemBuffer("# foo\n" + "\n" + "# bar"); + EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#')); + + Buffer = MemoryBuffer::getMemBuffer("\n" + "# baz\n" + "\n"); + EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#')); } } // anonymous namespace diff --git a/unittests/Support/LockFileManagerTest.cpp b/unittests/Support/LockFileManagerTest.cpp index 885b7d605367..efe3c3088b33 100644 --- a/unittests/Support/LockFileManagerTest.cpp +++ b/unittests/Support/LockFileManagerTest.cpp @@ -95,7 +95,7 @@ TEST(LockFileManagerTest, RelativePath) { char PathBuf[1024]; const char *OrigPath = getcwd(PathBuf, 1024); - chdir(TmpDir.c_str()); + ASSERT_FALSE(chdir(TmpDir.c_str())); sys::fs::create_directory("inner"); SmallString<64> LockedFile("inner"); @@ -118,7 +118,7 @@ TEST(LockFileManagerTest, RelativePath) { EC = sys::fs::remove("inner"); ASSERT_FALSE(EC); - chdir(OrigPath); + ASSERT_FALSE(chdir(OrigPath)); EC = sys::fs::remove(StringRef(TmpDir)); ASSERT_FALSE(EC); diff --git a/unittests/Support/MD5Test.cpp b/unittests/Support/MD5Test.cpp index 7c1331b6c537..c4fa5cd92c10 100644 --- a/unittests/Support/MD5Test.cpp +++ b/unittests/Support/MD5Test.cpp @@ -41,19 +41,19 @@ void TestMD5Sum(StringRef Input, StringRef Final) { } TEST(MD5Test, MD5) { - TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"", (size_t) 0), + TestMD5Sum(makeArrayRef((const uint8_t *)"", (size_t) 0), "d41d8cd98f00b204e9800998ecf8427e"); - TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"a", (size_t) 1), + TestMD5Sum(makeArrayRef((const uint8_t *)"a", (size_t) 1), "0cc175b9c0f1b6a831c399e269772661"); - TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", - (size_t) 26), + TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", + (size_t) 26), "c3fcd3d76192e4007dfb496cca67e13b"); - TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"\0", (size_t) 1), + TestMD5Sum(makeArrayRef((const uint8_t *)"\0", (size_t) 1), "93b885adfe0da089cdf634904fd59f71"); - TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"a\0", (size_t) 2), + TestMD5Sum(makeArrayRef((const uint8_t *)"a\0", (size_t) 2), "4144e195f46de78a3623da7364d04f11"); - TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0", - (size_t) 27), + TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0", + (size_t) 27), "81948d1f1554f58cd1a56ebb01f808cb"); TestMD5Sum("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); } diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 93bf301267ea..1cdd6adbf8ba 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -169,4 +169,54 @@ TEST_F(MemoryBufferTest, getOpenFileReopened) { testGetOpenFileSlice(true); } + +TEST_F(MemoryBufferTest, slice) { + // Create a file that is six pages long with different data on each page. + int FD; + SmallString<64> TestPath; + sys::fs::createTemporaryFile("MemoryBufferTest_Slice", "temp", FD, TestPath); + raw_fd_ostream OF(FD, true, /*unbuffered=*/true); + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "12345678"; + } + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "abcdefgh"; + } + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "ABCDEFGH"; + } + OF.close(); + + // Try offset of one page. + ErrorOr<OwningBuffer> MB = MemoryBuffer::getFileSlice(TestPath.str(), + 0x4000, 0x1000); + std::error_code EC = MB.getError(); + ASSERT_FALSE(EC); + EXPECT_EQ(0x4000UL, MB.get()->getBufferSize()); + + StringRef BufData = MB.get()->getBuffer(); + EXPECT_TRUE(BufData.substr(0x0000,8).equals("12345678")); + EXPECT_TRUE(BufData.substr(0x0FF8,8).equals("12345678")); + EXPECT_TRUE(BufData.substr(0x1000,8).equals("abcdefgh")); + EXPECT_TRUE(BufData.substr(0x2FF8,8).equals("abcdefgh")); + EXPECT_TRUE(BufData.substr(0x3000,8).equals("ABCDEFGH")); + EXPECT_TRUE(BufData.substr(0x3FF8,8).equals("ABCDEFGH")); + + // Try non-page aligned. + ErrorOr<OwningBuffer> MB2 = MemoryBuffer::getFileSlice(TestPath.str(), + 0x3000, 0x0800); + EC = MB2.getError(); + ASSERT_FALSE(EC); + EXPECT_EQ(0x3000UL, MB2.get()->getBufferSize()); + + StringRef BufData2 = MB2.get()->getBuffer(); + EXPECT_TRUE(BufData2.substr(0x0000,8).equals("12345678")); + EXPECT_TRUE(BufData2.substr(0x17F8,8).equals("12345678")); + EXPECT_TRUE(BufData2.substr(0x1800,8).equals("abcdefgh")); + EXPECT_TRUE(BufData2.substr(0x2FF8,8).equals("abcdefgh")); + +} + + + } diff --git a/unittests/Support/MemoryTest.cpp b/unittests/Support/MemoryTest.cpp index 8ad90e045de9..f439cb2af9b1 100644 --- a/unittests/Support/MemoryTest.cpp +++ b/unittests/Support/MemoryTest.cpp @@ -21,7 +21,7 @@ class MappedMemoryTest : public ::testing::TestWithParam<unsigned> { public: MappedMemoryTest() { Flags = GetParam(); - PageSize = sys::process::get_self()->page_size(); + PageSize = sys::Process::getPageSize(); } protected: diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index db85347e9212..0d661c8ae6c0 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -16,6 +16,7 @@ #include "gtest/gtest.h" #ifdef LLVM_ON_WIN32 +#include <Windows.h> #include <winerror.h> #endif @@ -141,7 +142,7 @@ TEST(Support, Path) { StringRef filename(temp_store.begin(), temp_store.size()), stem, ext; stem = path::stem(filename); ext = path::extension(filename); - EXPECT_EQ(*(--sys::path::end(filename)), (stem + ext).str()); + EXPECT_EQ(*sys::path::rbegin(filename), (stem + ext).str()); path::native(*i, temp_store); } @@ -227,7 +228,7 @@ TEST(Support, AbsolutePathIteratorEnd) { #endif for (StringRef Path : Paths) { - StringRef LastComponent = *--path::end(Path); + StringRef LastComponent = *path::rbegin(Path); EXPECT_EQ(".", LastComponent); } @@ -239,7 +240,7 @@ TEST(Support, AbsolutePathIteratorEnd) { #endif for (StringRef Path : RootPaths) { - StringRef LastComponent = *--path::end(Path); + StringRef LastComponent = *path::rbegin(Path); EXPECT_EQ(1u, LastComponent.size()); EXPECT_TRUE(path::is_separator(LastComponent[0])); } @@ -261,7 +262,7 @@ TEST(Support, HomeDirectory) { class FileSystemTest : public testing::Test { protected: /// Unique temporary directory in which all created filesystem entities must - /// be placed. It is recursively removed at the end of each test. + /// be placed. It is removed at the end of each test (must be empty). SmallString<128> TestDirectory; virtual void SetUp() { @@ -334,9 +335,7 @@ TEST_F(FileSystemTest, TempFiles) { fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); // Make sure it exists. - bool TempFileExists; - ASSERT_NO_ERROR(sys::fs::exists(Twine(TempPath), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); // Create another temp tile. int FD2; @@ -363,8 +362,8 @@ TEST_F(FileSystemTest, TempFiles) { EXPECT_EQ(B.type(), fs::file_type::file_not_found); // Make sure Temp2 doesn't exist. - ASSERT_NO_ERROR(fs::exists(Twine(TempPath2), TempFileExists)); - EXPECT_FALSE(TempFileExists); + ASSERT_EQ(fs::access(Twine(TempPath2), sys::fs::AccessMode::Exist), + errc::no_such_file_or_directory); SmallString<64> TempPath3; ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3)); @@ -387,8 +386,8 @@ TEST_F(FileSystemTest, TempFiles) { ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); // Make sure Temp1 doesn't exist. - ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists)); - EXPECT_FALSE(TempFileExists); + ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist), + errc::no_such_file_or_directory); #ifdef LLVM_ON_WIN32 // Path name > 260 chars should get an error. @@ -398,8 +397,16 @@ TEST_F(FileSystemTest, TempFiles) { "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; - EXPECT_EQ(fs::createUniqueFile(Twine(Path270), FileDescriptor, TempPath), - errc::no_such_file_or_directory); + EXPECT_EQ(fs::createUniqueFile(Path270, FileDescriptor, TempPath), + errc::invalid_argument); + // Relative path < 247 chars, no problem. + const char *Path216 = + "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" + "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" + "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" + "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; + ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath)); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); #endif } @@ -409,6 +416,54 @@ TEST_F(FileSystemTest, CreateDir) { ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), errc::file_exists); ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); + +#ifdef LLVM_ON_WIN32 + // Prove that create_directories() can handle a pathname > 248 characters, + // which is the documented limit for CreateDirectory(). + // (248 is MAX_PATH subtracting room for an 8.3 filename.) + // Generate a directory path guaranteed to fall into that range. + size_t TmpLen = TestDirectory.size(); + const char *OneDir = "\\123456789"; + size_t OneDirLen = strlen(OneDir); + ASSERT_LT(OneDirLen, 12U); + size_t NLevels = ((248 - TmpLen) / OneDirLen) + 1; + SmallString<260> LongDir(TestDirectory); + for (size_t I = 0; I < NLevels; ++I) + LongDir.append(OneDir); + ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); + ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); + ASSERT_EQ(fs::create_directories(Twine(LongDir), false), + errc::file_exists); + // Tidy up, "recursively" removing the directories. + StringRef ThisDir(LongDir); + for (size_t J = 0; J < NLevels; ++J) { + ASSERT_NO_ERROR(fs::remove(ThisDir)); + ThisDir = path::parent_path(ThisDir); + } + + // Similarly for a relative pathname. Need to set the current directory to + // TestDirectory so that the one we create ends up in the right place. + char PreviousDir[260]; + size_t PreviousDirLen = ::GetCurrentDirectoryA(260, PreviousDir); + ASSERT_GT(PreviousDirLen, 0U); + ASSERT_LT(PreviousDirLen, 260U); + ASSERT_NE(::SetCurrentDirectoryA(TestDirectory.c_str()), 0); + LongDir.clear(); + // Generate a relative directory name with absolute length > 248. + size_t LongDirLen = 249 - TestDirectory.size(); + LongDir.assign(LongDirLen, 'a'); + ASSERT_NO_ERROR(fs::create_directory(Twine(LongDir))); + // While we're here, prove that .. and . handling works in these long paths. + const char *DotDotDirs = "\\..\\.\\b"; + LongDir.append(DotDotDirs); + ASSERT_NO_ERROR(fs::create_directory("b")); + ASSERT_EQ(fs::create_directory(Twine(LongDir), false), errc::file_exists); + // And clean up. + ASSERT_NO_ERROR(fs::remove("b")); + ASSERT_NO_ERROR(fs::remove( + Twine(LongDir.substr(0, LongDir.size() - strlen(DotDotDirs))))); + ASSERT_NE(::SetCurrentDirectoryA(PreviousDir), 0); +#endif } TEST_F(FileSystemTest, DirectoryIteration) { @@ -485,6 +540,8 @@ TEST_F(FileSystemTest, DirectoryIteration) { const char archive[] = "!<arch>\x0A"; const char bitcode[] = "\xde\xc0\x17\x0b"; const char coff_object[] = "\x00\x00......"; +const char coff_bigobj[] = "\x00\x00\xff\xff\x00\x02......" + "\xc7\xa1\xba\xd1\xee\xba\xa9\x4b\xaf\x20\xfa\xf6\x6a\xa4\xdc\xb8"; 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 }; @@ -501,6 +558,8 @@ 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 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"; TEST_F(FileSystemTest, Magic) { struct type { @@ -514,6 +573,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(archive), DEFINE(bitcode), DEFINE(coff_object), + { "coff_bigobj", coff_bigobj, sizeof(coff_bigobj), fs::file_magic::coff_object }, DEFINE(coff_import_library), DEFINE(elf_relocatable), DEFINE(macho_universal_binary), @@ -525,6 +585,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(macho_dynamically_linked_shared_lib), DEFINE(macho_dynamic_linker), DEFINE(macho_bundle), + DEFINE(macho_dynamically_linked_shared_lib_stub), DEFINE(macho_dsym_companion), DEFINE(windows_resource) #undef DEFINE @@ -535,8 +596,8 @@ TEST_F(FileSystemTest, Magic) { ++i) { SmallString<128> file_pathname(TestDirectory); path::append(file_pathname, i->filename); - std::string ErrMsg; - raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_None); + std::error_code EC; + raw_fd_ostream file(file_pathname, EC, sys::fs::F_None); ASSERT_FALSE(file.has_error()); StringRef magic(i->magic_str, i->magic_str_len); file << magic; @@ -549,27 +610,27 @@ TEST_F(FileSystemTest, Magic) { #ifdef LLVM_ON_WIN32 TEST_F(FileSystemTest, CarriageReturn) { SmallString<128> FilePathname(TestDirectory); - std::string ErrMsg; + std::error_code EC; path::append(FilePathname, "test"); { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Text); - EXPECT_EQ(ErrMsg, ""); + raw_fd_ostream File(FilePathname, EC, sys::fs::F_Text); + ASSERT_NO_ERROR(EC); File << '\n'; } { - auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); + auto Buf = MemoryBuffer::getFile(FilePathname.str()); EXPECT_TRUE((bool)Buf); EXPECT_EQ(Buf.get()->getBuffer(), "\r\n"); } { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_None); - EXPECT_EQ(ErrMsg, ""); + raw_fd_ostream File(FilePathname, EC, sys::fs::F_None); + ASSERT_NO_ERROR(EC); File << '\n'; } { - auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); + auto Buf = MemoryBuffer::getFile(FilePathname.str()); EXPECT_TRUE((bool)Buf); EXPECT_EQ(Buf.get()->getBuffer(), "\n"); } @@ -577,22 +638,31 @@ TEST_F(FileSystemTest, CarriageReturn) { } #endif +TEST_F(FileSystemTest, Resize) { + int FD; + SmallString<64> TempPath; + ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); + ASSERT_NO_ERROR(fs::resize_file(FD, 123)); + fs::file_status Status; + ASSERT_NO_ERROR(fs::status(FD, Status)); + ASSERT_EQ(Status.getSize(), 123U); +} + TEST_F(FileSystemTest, FileMapping) { // Create a temp file. int FileDescriptor; SmallString<64> TempPath; ASSERT_NO_ERROR( fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); + unsigned Size = 4096; + ASSERT_NO_ERROR(fs::resize_file(FileDescriptor, Size)); + // Map in temp file and add some content std::error_code EC; StringRef Val("hello there"); { fs::mapped_file_region mfr(FileDescriptor, - true, - fs::mapped_file_region::readwrite, - 4096, - 0, - EC); + fs::mapped_file_region::readwrite, Size, 0, EC); ASSERT_NO_ERROR(EC); std::copy(Val.begin(), Val.end(), mfr.data()); // Explicitly add a 0. @@ -601,27 +671,19 @@ TEST_F(FileSystemTest, FileMapping) { } // Map it back in read-only - fs::mapped_file_region mfr(Twine(TempPath), - fs::mapped_file_region::readonly, - 0, - 0, - EC); + int FD; + EC = fs::openFileForRead(Twine(TempPath), FD); + ASSERT_NO_ERROR(EC); + fs::mapped_file_region mfr(FD, fs::mapped_file_region::readonly, Size, 0, EC); ASSERT_NO_ERROR(EC); // Verify content EXPECT_EQ(StringRef(mfr.const_data()), Val); // Unmap temp file - - fs::mapped_file_region m(Twine(TempPath), - fs::mapped_file_region::readonly, - 0, - 0, - EC); + fs::mapped_file_region m(FD, fs::mapped_file_region::readonly, Size, 0, EC); ASSERT_NO_ERROR(EC); - const char *Data = m.const_data(); - fs::mapped_file_region mfrrv(std::move(m)); - EXPECT_EQ(mfrrv.const_data(), Data); + ASSERT_EQ(close(FD), 0); } TEST(Support, NormalizePath) { @@ -640,22 +702,22 @@ TEST(Support, NormalizePath) { SmallString<64> Path5("\\a"); SmallString<64> Path6("a\\"); - ASSERT_NO_ERROR(fs::normalize_separators(Path1)); + path::native(Path1); EXPECT_PATH_IS(Path1, "a", "a"); - ASSERT_NO_ERROR(fs::normalize_separators(Path2)); - EXPECT_PATH_IS(Path2, "a/b", "a/b"); + path::native(Path2); + EXPECT_PATH_IS(Path2, "a\\b", "a/b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path3)); + path::native(Path3); EXPECT_PATH_IS(Path3, "a\\b", "a/b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path4)); + path::native(Path4); EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path5)); + path::native(Path5); EXPECT_PATH_IS(Path5, "\\a", "/a"); - ASSERT_NO_ERROR(fs::normalize_separators(Path6)); + path::native(Path6); EXPECT_PATH_IS(Path6, "a\\", "a/"); #undef EXPECT_PATH_IS diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp index f4060720961b..298a0a373234 100644 --- a/unittests/Support/ProcessTest.cpp +++ b/unittests/Support/ProcessTest.cpp @@ -19,26 +19,6 @@ namespace { using namespace llvm; using namespace sys; -TEST(ProcessTest, SelfProcess) { - EXPECT_TRUE(process::get_self()); - EXPECT_EQ(process::get_self(), process::get_self()); - -#if defined(LLVM_ON_UNIX) - EXPECT_EQ(getpid(), process::get_self()->get_id()); -#elif defined(LLVM_ON_WIN32) - EXPECT_EQ(GetCurrentProcessId(), process::get_self()->get_id()); -#endif - - EXPECT_LT(1u, process::get_self()->page_size()); - - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_user_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_user_time()); - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_system_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_system_time()); - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_wall_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_wall_time()); -} - TEST(ProcessTest, GetRandomNumberTest) { const unsigned r1 = Process::GetRandomNumber(); const unsigned r2 = Process::GetRandomNumber(); diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index 4e7316fb3ace..0feed47b59d9 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -34,6 +34,16 @@ void sleep_for(unsigned int seconds) { #error sleep_for is not implemented on your platform. #endif +#define ASSERT_NO_ERROR(x) \ + if (std::error_code ASSERT_NO_ERROR_ec = x) { \ + SmallString<128> MessageStorage; \ + raw_svector_ostream Message(MessageStorage); \ + Message << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ + } else { \ + } // From TestMain.cpp. extern const char *TestMainArgv0; @@ -60,6 +70,56 @@ static void CopyEnvironment(std::vector<const char *> &out) { } } +#ifdef LLVM_ON_WIN32 +TEST(ProgramTest, CreateProcessLongPath) { + if (getenv("LLVM_PROGRAM_TEST_LONG_PATH")) + exit(0); + + // getMainExecutable returns an absolute path; prepend the long-path prefix. + std::string MyAbsExe = + sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); + std::string MyExe; + if (!StringRef(MyAbsExe).startswith("\\\\?\\")) + MyExe.append("\\\\?\\"); + MyExe.append(MyAbsExe); + + const char *ArgV[] = { + MyExe.c_str(), + "--gtest_filter=ProgramTest.CreateProcessLongPath", + nullptr + }; + + // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child. + std::vector<const char *> EnvP; + CopyEnvironment(EnvP); + EnvP.push_back("LLVM_PROGRAM_TEST_LONG_PATH=1"); + EnvP.push_back(nullptr); + + // Redirect stdout to a long path. + SmallString<128> TestDirectory; + ASSERT_NO_ERROR( + fs::createUniqueDirectory("program-redirect-test", TestDirectory)); + SmallString<256> LongPath(TestDirectory); + LongPath.push_back('\\'); + // MAX_PATH = 260 + LongPath.append(260 - TestDirectory.size(), 'a'); + StringRef LongPathRef(LongPath); + + std::string Error; + bool ExecutionFailed; + const StringRef *Redirects[] = { nullptr, &LongPathRef, nullptr }; + int RC = ExecuteAndWait(MyExe, ArgV, &EnvP[0], Redirects, + /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &Error, + &ExecutionFailed); + EXPECT_FALSE(ExecutionFailed) << Error; + EXPECT_EQ(0, RC); + + // Remove the long stdout. + ASSERT_NO_ERROR(fs::remove(Twine(LongPath))); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory))); +} +#endif + TEST(ProgramTest, CreateProcessTrailingSlash) { if (getenv("LLVM_PROGRAM_TEST_CHILD")) { if (ProgramTestStringArg1 == "has\\\\ trailing\\" && @@ -220,4 +280,44 @@ TEST(ProgramTest, TestExecuteNegative) { } +#ifdef LLVM_ON_WIN32 +const char utf16le_text[] = + "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00"; +const char utf16be_text[] = + "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61"; +#endif +const char utf8_text[] = "\x6c\x69\x6e\x67\xc3\xbc\x69\xc3\xa7\x61"; + +TEST(ProgramTest, TestWriteWithSystemEncoding) { + SmallString<128> TestDirectory; + ASSERT_NO_ERROR(fs::createUniqueDirectory("program-test", TestDirectory)); + errs() << "Test Directory: " << TestDirectory << '\n'; + errs().flush(); + SmallString<128> file_pathname(TestDirectory); + path::append(file_pathname, "international-file.txt"); + // Only on Windows we should encode in UTF16. For other systems, use UTF8 + ASSERT_NO_ERROR(sys::writeFileWithEncoding(file_pathname.c_str(), utf8_text, + sys::WEM_UTF16)); + int fd = 0; + ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd)); +#if defined(LLVM_ON_WIN32) + char buf[18]; + ASSERT_EQ(::read(fd, buf, 18), 18); + if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE + ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0); + } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE + ASSERT_EQ(strncmp(&buf[2], utf16le_text, 16), 0); + } else { + FAIL() << "Invalid BOM in UTF-16 file"; + } +#else + char buf[10]; + ASSERT_EQ(::read(fd, buf, 10), 10); + ASSERT_EQ(strncmp(buf, utf8_text, 10), 0); +#endif + ::close(fd); + ASSERT_NO_ERROR(fs::remove(file_pathname.str())); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); +} + } // end anonymous namespace diff --git a/unittests/Support/ScaledNumberTest.cpp b/unittests/Support/ScaledNumberTest.cpp index 7bbef7e4e58d..d8d6e310ff9f 100644 --- a/unittests/Support/ScaledNumberTest.cpp +++ b/unittests/Support/ScaledNumberTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ScaledNumber.h" - #include "llvm/Support/DataTypes.h" #include "gtest/gtest.h" diff --git a/unittests/Support/SourceMgrTest.cpp b/unittests/Support/SourceMgrTest.cpp index 2b69fe984445..79c2d7278f12 100644 --- a/unittests/Support/SourceMgrTest.cpp +++ b/unittests/Support/SourceMgrTest.cpp @@ -23,8 +23,9 @@ public: std::string Output; void setMainBuffer(StringRef Text, StringRef BufferName) { - MemoryBuffer *MainBuffer = MemoryBuffer::getMemBuffer(Text, BufferName); - MainBufferID = SM.AddNewSourceBuffer(MainBuffer, llvm::SMLoc()); + std::unique_ptr<MemoryBuffer> MainBuffer = + MemoryBuffer::getMemBuffer(Text, BufferName); + MainBufferID = SM.AddNewSourceBuffer(std::move(MainBuffer), llvm::SMLoc()); } SMLoc getLoc(unsigned Offset) { diff --git a/unittests/Support/SpecialCaseListTest.cpp b/unittests/Support/SpecialCaseListTest.cpp index bb9c351415bf..740dbfef4044 100644 --- a/unittests/Support/SpecialCaseListTest.cpp +++ b/unittests/Support/SpecialCaseListTest.cpp @@ -17,14 +17,15 @@ namespace { class SpecialCaseListTest : public ::testing::Test { protected: - SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { - std::unique_ptr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List)); + std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List, + std::string &Error) { + std::unique_ptr<MemoryBuffer> MB = MemoryBuffer::getMemBuffer(List); return SpecialCaseList::create(MB.get(), Error); } - SpecialCaseList *makeSpecialCaseList(StringRef List) { + std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List) { std::string Error; - SpecialCaseList *SCL = makeSpecialCaseList(List, Error); + auto SCL = makeSpecialCaseList(List, Error); assert(SCL); assert(Error == ""); return SCL; @@ -32,13 +33,13 @@ protected: }; TEST_F(SpecialCaseListTest, Basic) { - std::unique_ptr<SpecialCaseList> SCL( + std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("# This is a comment.\n" "\n" "src:hello\n" "src:bye\n" "src:hi=category\n" - "src:z*=category\n")); + "src:z*=category\n"); EXPECT_TRUE(SCL->inSection("src", "hello")); EXPECT_TRUE(SCL->inSection("src", "bye")); EXPECT_TRUE(SCL->inSection("src", "hi", "category")); @@ -48,39 +49,21 @@ TEST_F(SpecialCaseListTest, Basic) { EXPECT_FALSE(SCL->inSection("src", "hello", "category")); } -TEST_F(SpecialCaseListTest, GlobalInitCompat) { - std::unique_ptr<SpecialCaseList> SCL( - makeSpecialCaseList("global:foo=init\n")); +TEST_F(SpecialCaseListTest, GlobalInit) { + std::unique_ptr<SpecialCaseList> SCL = + makeSpecialCaseList("global:foo=init\n"); EXPECT_FALSE(SCL->inSection("global", "foo")); EXPECT_FALSE(SCL->inSection("global", "bar")); EXPECT_TRUE(SCL->inSection("global", "foo", "init")); EXPECT_FALSE(SCL->inSection("global", "bar", "init")); - SCL.reset(makeSpecialCaseList("global-init:foo\n")); - EXPECT_FALSE(SCL->inSection("global", "foo")); - EXPECT_FALSE(SCL->inSection("global", "bar")); - EXPECT_TRUE(SCL->inSection("global", "foo", "init")); - EXPECT_FALSE(SCL->inSection("global", "bar", "init")); - - SCL.reset(makeSpecialCaseList("type:t2=init\n")); + SCL = makeSpecialCaseList("type:t2=init\n"); EXPECT_FALSE(SCL->inSection("type", "t1")); EXPECT_FALSE(SCL->inSection("type", "t2")); EXPECT_FALSE(SCL->inSection("type", "t1", "init")); EXPECT_TRUE(SCL->inSection("type", "t2", "init")); - SCL.reset(makeSpecialCaseList("global-init-type:t2\n")); - EXPECT_FALSE(SCL->inSection("type", "t1")); - EXPECT_FALSE(SCL->inSection("type", "t2")); - EXPECT_FALSE(SCL->inSection("type", "t1", "init")); - EXPECT_TRUE(SCL->inSection("type", "t2", "init")); - - SCL.reset(makeSpecialCaseList("src:hello=init\n")); - EXPECT_FALSE(SCL->inSection("src", "hello")); - EXPECT_FALSE(SCL->inSection("src", "bye")); - EXPECT_TRUE(SCL->inSection("src", "hello", "init")); - EXPECT_FALSE(SCL->inSection("src", "bye", "init")); - - SCL.reset(makeSpecialCaseList("global-init-src:hello\n")); + SCL = makeSpecialCaseList("src:hello=init\n"); EXPECT_FALSE(SCL->inSection("src", "hello")); EXPECT_FALSE(SCL->inSection("src", "bye")); EXPECT_TRUE(SCL->inSection("src", "hello", "init")); @@ -88,14 +71,14 @@ TEST_F(SpecialCaseListTest, GlobalInitCompat) { } TEST_F(SpecialCaseListTest, Substring) { - std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n" - "fun:foo\n" - "global:bar\n")); + std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:hello\n" + "fun:foo\n" + "global:bar\n"); EXPECT_FALSE(SCL->inSection("src", "othello")); EXPECT_FALSE(SCL->inSection("fun", "tomfoolery")); EXPECT_FALSE(SCL->inSection("global", "bartender")); - SCL.reset(makeSpecialCaseList("fun:*foo*\n")); + SCL = makeSpecialCaseList("fun:*foo*\n"); EXPECT_TRUE(SCL->inSection("fun", "tomfoolery")); EXPECT_TRUE(SCL->inSection("fun", "foobar")); } @@ -117,7 +100,7 @@ TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { } TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { - std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("")); + std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList(""); EXPECT_FALSE(SCL->inSection("foo", "bar")); } diff --git a/unittests/Support/StreamingMemoryObject.cpp b/unittests/Support/StreamingMemoryObject.cpp new file mode 100644 index 000000000000..20136491ab8b --- /dev/null +++ b/unittests/Support/StreamingMemoryObject.cpp @@ -0,0 +1,29 @@ +//===- 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/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 = new NullDataStreamer(); + StreamingMemoryObject O(DS); + EXPECT_TRUE(O.isValidAddress(32 * 1024)); +} diff --git a/unittests/Support/StringPool.cpp b/unittests/Support/StringPool.cpp index 7b7805f91710..ac39fec059e5 100644 --- a/unittests/Support/StringPool.cpp +++ b/unittests/Support/StringPool.cpp @@ -1,6 +1,6 @@ -//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===// +//===- llvm/unittest/Support/StringPoiil.cpp - StringPool tests -----------===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. diff --git a/unittests/Support/ThreadLocalTest.cpp b/unittests/Support/ThreadLocalTest.cpp index ea751be230cc..e71c7dba22fc 100644 --- a/unittests/Support/ThreadLocalTest.cpp +++ b/unittests/Support/ThreadLocalTest.cpp @@ -1,6 +1,6 @@ -//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===// +//===- llvm/unittest/Support/ThreadLocalTest.cpp - ThreadLocal tests ------===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. @@ -9,6 +9,7 @@ #include "llvm/Support/ThreadLocal.h" #include "gtest/gtest.h" +#include <type_traits> using namespace llvm; using namespace sys; @@ -25,6 +26,10 @@ struct S { TEST_F(ThreadLocalTest, Basics) { ThreadLocal<const S> x; + static_assert( + std::is_const<std::remove_pointer<decltype(x.get())>::type>::value, + "ThreadLocal::get didn't return a pointer to const object"); + EXPECT_EQ(nullptr, x.get()); S s; @@ -33,6 +38,20 @@ TEST_F(ThreadLocalTest, Basics) { x.erase(); EXPECT_EQ(nullptr, x.get()); + + ThreadLocal<S> y; + + static_assert( + !std::is_const<std::remove_pointer<decltype(y.get())>::type>::value, + "ThreadLocal::get returned a pointer to const object"); + + EXPECT_EQ(nullptr, y.get()); + + y.set(&s); + EXPECT_EQ(&s, y.get()); + + y.erase(); + EXPECT_EQ(nullptr, y.get()); } } diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 8aed98012f10..074e27f8318d 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -84,6 +84,13 @@ TEST(YAMLIO, TestMapRead) { } } +TEST(YAMLIO, TestMalformedMapRead) { + FooBar doc; + Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages); + yin >> doc; + EXPECT_TRUE(!!yin.error()); +} + // // Test the reading of a yaml sequence of mappings // diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp index e9839358a019..823a0d6e3e03 100644 --- a/unittests/Support/YAMLParserTest.cpp +++ b/unittests/Support/YAMLParserTest.cpp @@ -18,7 +18,7 @@ namespace llvm { static void SuppressDiagnosticsOutput(const SMDiagnostic &, void *) { - // Prevent SourceMgr from writing errors to stderr + // Prevent SourceMgr from writing errors to stderr // to reduce noise in unit test runs. } @@ -210,8 +210,9 @@ TEST(YAMLParser, DiagnosticFilenameFromBufferID) { // When we construct a YAML stream over a named buffer, // we get its ID as filename in diagnostics. - MemoryBuffer* Buffer = MemoryBuffer::getMemBuffer("[]", "buffername.yaml"); - yaml::Stream Stream(Buffer, SM); + std::unique_ptr<MemoryBuffer> Buffer = + MemoryBuffer::getMemBuffer("[]", "buffername.yaml"); + yaml::Stream Stream(Buffer->getMemBufferRef(), SM); Stream.printError(Stream.begin()->getRoot(), "Hello, World!"); EXPECT_EQ("buffername.yaml", GeneratedDiag.getFilename()); } diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index 44d27d041021..39cfaf004c72 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -143,4 +143,41 @@ TEST(raw_ostreamTest, WriteEscaped) { EXPECT_EQ("\\001\\010\\200", Str); } +TEST(raw_ostreamTest, Justify) { + EXPECT_EQ("xyz ", printToString(left_justify("xyz", 6), 6)); + EXPECT_EQ("abc", printToString(left_justify("abc", 3), 3)); + EXPECT_EQ("big", printToString(left_justify("big", 1), 3)); + EXPECT_EQ(" xyz", printToString(right_justify("xyz", 6), 6)); + EXPECT_EQ("abc", printToString(right_justify("abc", 3), 3)); + EXPECT_EQ("big", printToString(right_justify("big", 1), 3)); +} + +TEST(raw_ostreamTest, FormatHex) { + EXPECT_EQ("0x1234", printToString(format_hex(0x1234, 6), 6)); + EXPECT_EQ("0x001234", printToString(format_hex(0x1234, 8), 8)); + EXPECT_EQ("0x00001234", printToString(format_hex(0x1234, 10), 10)); + EXPECT_EQ("0x1234", printToString(format_hex(0x1234, 4), 6)); + EXPECT_EQ("0xff", printToString(format_hex(255, 4), 4)); + EXPECT_EQ("0xFF", printToString(format_hex(255, 4, true), 4)); + 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("0xffffffffffffffff", + printToString(format_hex(UINT64_MAX, 18), 18)); + EXPECT_EQ("0x8000000000000000", + printToString(format_hex((INT64_MIN), 18), 18)); +} + +TEST(raw_ostreamTest, FormatDecimal) { + EXPECT_EQ(" 0", printToString(format_decimal(0, 4), 4)); + EXPECT_EQ(" -1", printToString(format_decimal(-1, 4), 4)); + EXPECT_EQ(" -1", printToString(format_decimal(-1, 6), 6)); + EXPECT_EQ("1234567890", printToString(format_decimal(1234567890, 10), 10)); + EXPECT_EQ(" 9223372036854775807", + printToString(format_decimal(INT64_MAX, 21), 21)); + EXPECT_EQ(" -9223372036854775808", + printToString(format_decimal(INT64_MIN, 21), 21)); +} + + } |