diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:41:23 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:41:23 +0000 |
commit | 169d2bd06003c39970bc94c99669a34b61bb7e45 (patch) | |
tree | 06099edc18d30894081a822b756f117cbe0b8207 /unittests/Support | |
parent | 0ac5f94c68a3d8fbd1380dbba26d891ea7816b5e (diff) | |
download | FreeBSD-src-169d2bd06003c39970bc94c99669a34b61bb7e45.zip FreeBSD-src-169d2bd06003c39970bc94c99669a34b61bb7e45.tar.gz |
Vendor import of llvm trunk r178860:
http://llvm.org/svn/llvm-project/llvm/trunk@178860
Diffstat (limited to 'unittests/Support')
22 files changed, 2058 insertions, 420 deletions
diff --git a/unittests/Support/AlignOfTest.cpp b/unittests/Support/AlignOfTest.cpp index f01e660..40f7295 100644 --- a/unittests/Support/AlignOfTest.cpp +++ b/unittests/Support/AlignOfTest.cpp @@ -9,19 +9,29 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" - #include "gtest/gtest.h" using namespace llvm; namespace { - // Disable warnings about questionable type definitions. // We're testing that even questionable types work with the alignment utilities. #ifdef _MSC_VER #pragma warning(disable:4584) #endif +// Suppress direct base '{anonymous}::S1' inaccessible in '{anonymous}::D9' +// due to ambiguity warning. +// +// 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 { }; @@ -310,6 +320,16 @@ TEST(AlignOfTest, BasicAlignedArray) { #ifndef _MSC_VER EXPECT_EQ(sizeof(V8), sizeof(AlignedCharArrayUnion<V8>)); #endif -} + EXPECT_EQ(1u, (alignOf<AlignedCharArray<1, 1> >())); + EXPECT_EQ(2u, (alignOf<AlignedCharArray<2, 1> >())); + EXPECT_EQ(4u, (alignOf<AlignedCharArray<4, 1> >())); + EXPECT_EQ(8u, (alignOf<AlignedCharArray<8, 1> >())); + EXPECT_EQ(16u, (alignOf<AlignedCharArray<16, 1> >())); + + EXPECT_EQ(1u, sizeof(AlignedCharArray<1, 1>)); + EXPECT_EQ(7u, sizeof(AlignedCharArray<1, 7>)); + EXPECT_EQ(2u, sizeof(AlignedCharArray<2, 2>)); + EXPECT_EQ(16u, sizeof(AlignedCharArray<2, 16>)); +} } diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index 8b463c1..cb9fa43 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Allocator.h" - #include "gtest/gtest.h" #include <cstdlib> diff --git a/unittests/Support/ArrayRecyclerTest.cpp b/unittests/Support/ArrayRecyclerTest.cpp new file mode 100644 index 0000000..1ff97ba --- /dev/null +++ b/unittests/Support/ArrayRecyclerTest.cpp @@ -0,0 +1,109 @@ +//===--- unittest/Support/ArrayRecyclerTest.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/ArrayRecycler.h" +#include "llvm/Support/Allocator.h" +#include "gtest/gtest.h" +#include <cstdlib> + +using namespace llvm; + +namespace { + +struct Object { + int Num; + Object *Other; +}; +typedef ArrayRecycler<Object> ARO; + +TEST(ArrayRecyclerTest, Capacity) { + // Capacity size should never be 0. + ARO::Capacity Cap = ARO::Capacity::get(0); + EXPECT_LT(0u, Cap.getSize()); + + size_t PrevSize = Cap.getSize(); + for (unsigned N = 1; N != 100; ++N) { + Cap = ARO::Capacity::get(N); + EXPECT_LE(N, Cap.getSize()); + if (PrevSize >= N) + EXPECT_EQ(PrevSize, Cap.getSize()); + else + EXPECT_LT(PrevSize, Cap.getSize()); + PrevSize = Cap.getSize(); + } + + // Check that the buckets are monotonically increasing. + Cap = ARO::Capacity::get(0); + PrevSize = Cap.getSize(); + for (unsigned N = 0; N != 20; ++N) { + Cap = Cap.getNext(); + EXPECT_LT(PrevSize, Cap.getSize()); + PrevSize = Cap.getSize(); + } +} + +TEST(ArrayRecyclerTest, Basics) { + BumpPtrAllocator Allocator; + ArrayRecycler<Object> DUT; + + ARO::Capacity Cap = ARO::Capacity::get(8); + Object *A1 = DUT.allocate(Cap, Allocator); + A1[0].Num = 21; + A1[7].Num = 17; + + Object *A2 = DUT.allocate(Cap, Allocator); + A2[0].Num = 121; + A2[7].Num = 117; + + Object *A3 = DUT.allocate(Cap, Allocator); + A3[0].Num = 221; + A3[7].Num = 217; + + EXPECT_EQ(21, A1[0].Num); + EXPECT_EQ(17, A1[7].Num); + EXPECT_EQ(121, A2[0].Num); + EXPECT_EQ(117, A2[7].Num); + EXPECT_EQ(221, A3[0].Num); + EXPECT_EQ(217, A3[7].Num); + + DUT.deallocate(Cap, A2); + + // Check that deallocation didn't clobber anything. + EXPECT_EQ(21, A1[0].Num); + EXPECT_EQ(17, A1[7].Num); + EXPECT_EQ(221, A3[0].Num); + EXPECT_EQ(217, A3[7].Num); + + // Verify recycling. + Object *A2x = DUT.allocate(Cap, Allocator); + EXPECT_EQ(A2, A2x); + + DUT.deallocate(Cap, A2x); + DUT.deallocate(Cap, A1); + DUT.deallocate(Cap, A3); + + // Objects are not required to be recycled in reverse deallocation order, but + // that is what the current implementation does. + Object *A3x = DUT.allocate(Cap, Allocator); + EXPECT_EQ(A3, A3x); + Object *A1x = DUT.allocate(Cap, Allocator); + EXPECT_EQ(A1, A1x); + Object *A2y = DUT.allocate(Cap, Allocator); + EXPECT_EQ(A2, A2y); + + // Back to allocation from the BumpPtrAllocator. + Object *A4 = DUT.allocate(Cap, Allocator); + EXPECT_NE(A1, A4); + EXPECT_NE(A2, A4); + EXPECT_NE(A3, A4); + + DUT.clear(Allocator); +} + +} // end anonymous namespace diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp index 9c5bd7b..ff66bc4 100644 --- a/unittests/Support/BlockFrequencyTest.cpp +++ b/unittests/Support/BlockFrequencyTest.cpp @@ -1,7 +1,6 @@ -#include "llvm/Support/DataTypes.h" #include "llvm/Support/BlockFrequency.h" #include "llvm/Support/BranchProbability.h" - +#include "llvm/Support/DataTypes.h" #include "gtest/gtest.h" #include <climits> diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 09a0ea5..b4b982f 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -6,12 +6,14 @@ set(LLVM_LINK_COMPONENTS add_llvm_unittest(SupportTests AlignOfTest.cpp AllocatorTest.cpp + ArrayRecyclerTest.cpp BlockFrequencyTest.cpp Casting.cpp CommandLineTest.cpp ConstantRangeTest.cpp DataExtractorTest.cpp EndianTest.cpp + ErrorOrTest.cpp FileOutputBufferTest.cpp IntegersSubsetTest.cpp LeakDetectorTest.cpp @@ -20,10 +22,12 @@ add_llvm_unittest(SupportTests MemoryBufferTest.cpp MemoryTest.cpp Path.cpp + ProcessTest.cpp RegexTest.cpp SwapByteOrderTest.cpp TimeValue.cpp ValueHandleTest.cpp + YAMLIOTest.cpp YAMLParserTest.cpp formatted_raw_ostream_test.cpp raw_ostream_test.cpp diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp index ad564aa..01583e4 100644 --- a/unittests/Support/Casting.cpp +++ b/unittests/Support/Casting.cpp @@ -10,7 +10,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" - #include "gtest/gtest.h" #include <cstdlib> diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index 13e9038..43c8cbd 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -9,11 +9,9 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Config/config.h" - #include "gtest/gtest.h" - -#include <string> #include <stdlib.h> +#include <string> using namespace llvm; diff --git a/unittests/Support/ConstantRangeTest.cpp b/unittests/Support/ConstantRangeTest.cpp index 263f93c..4d6bbf6 100644 --- a/unittests/Support/ConstantRangeTest.cpp +++ b/unittests/Support/ConstantRangeTest.cpp @@ -8,8 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ConstantRange.h" -#include "llvm/Instructions.h" - +#include "llvm/IR/Instructions.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/Support/EndianTest.cpp b/unittests/Support/EndianTest.cpp index 6fe0247..8f93553 100644 --- a/unittests/Support/EndianTest.cpp +++ b/unittests/Support/EndianTest.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "gtest/gtest.h" #include "llvm/Support/Endian.h" #include "llvm/Support/DataTypes.h" +#include "gtest/gtest.h" #include <cstdlib> #include <ctime> using namespace llvm; @@ -21,36 +21,36 @@ namespace { TEST(Endian, Read) { // These are 5 bytes so we can be sure at least one of the reads is unaligned. - unsigned char big[] = {0x00, 0x01, 0x02, 0x03, 0x04}; - unsigned char little[] = {0x00, 0x04, 0x03, 0x02, 0x01}; + unsigned char bigval[] = {0x00, 0x01, 0x02, 0x03, 0x04}; + unsigned char littleval[] = {0x00, 0x04, 0x03, 0x02, 0x01}; int32_t BigAsHost = 0x00010203; - EXPECT_EQ(BigAsHost, (endian::read_be<int32_t, unaligned>(big))); + EXPECT_EQ(BigAsHost, (endian::read<int32_t, big, unaligned>(bigval))); int32_t LittleAsHost = 0x02030400; - EXPECT_EQ(LittleAsHost, (endian::read_le<int32_t, unaligned>(little))); + EXPECT_EQ(LittleAsHost,(endian::read<int32_t, little, unaligned>(littleval))); - EXPECT_EQ((endian::read_be<int32_t, unaligned>(big + 1)), - (endian::read_le<int32_t, unaligned>(little + 1))); + EXPECT_EQ((endian::read<int32_t, big, unaligned>(bigval + 1)), + (endian::read<int32_t, little, unaligned>(littleval + 1))); } TEST(Endian, Write) { unsigned char data[5]; - endian::write_be<int32_t, unaligned>(data, -1362446643); + endian::write<int32_t, big, unaligned>(data, -1362446643); EXPECT_EQ(data[0], 0xAE); EXPECT_EQ(data[1], 0xCA); EXPECT_EQ(data[2], 0xB6); EXPECT_EQ(data[3], 0xCD); - endian::write_be<int32_t, unaligned>(data + 1, -1362446643); + endian::write<int32_t, big, unaligned>(data + 1, -1362446643); EXPECT_EQ(data[1], 0xAE); EXPECT_EQ(data[2], 0xCA); EXPECT_EQ(data[3], 0xB6); EXPECT_EQ(data[4], 0xCD); - endian::write_le<int32_t, unaligned>(data, -1362446643); + endian::write<int32_t, little, unaligned>(data, -1362446643); EXPECT_EQ(data[0], 0xCD); EXPECT_EQ(data[1], 0xB6); EXPECT_EQ(data[2], 0xCA); EXPECT_EQ(data[3], 0xAE); - endian::write_le<int32_t, unaligned>(data + 1, -1362446643); + endian::write<int32_t, little, unaligned>(data + 1, -1362446643); EXPECT_EQ(data[1], 0xCD); EXPECT_EQ(data[2], 0xB6); EXPECT_EQ(data[3], 0xCA); @@ -69,4 +69,4 @@ TEST(Endian, PackedEndianSpecificIntegral) { EXPECT_EQ(*big_val, *little_val); } -} +} // end anon namespace diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp new file mode 100644 index 0000000..4853426 --- /dev/null +++ b/unittests/Support/ErrorOrTest.cpp @@ -0,0 +1,104 @@ +//===- unittests/ErrorOrTest.cpp - ErrorOr.h tests ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ErrorOr.h" + +#include "gtest/gtest.h" + +#include <memory> + +using namespace llvm; + +namespace { + +ErrorOr<int> t1() {return 1;} +ErrorOr<int> t2() { return errc::invalid_argument; } + +TEST(ErrorOr, SimpleValue) { + ErrorOr<int> a = t1(); + EXPECT_TRUE(a); + EXPECT_EQ(1, *a); + + a = t2(); + EXPECT_FALSE(a); + EXPECT_EQ(errc::invalid_argument, a); +#ifdef EXPECT_DEBUG_DEATH + EXPECT_DEBUG_DEATH(*a, "Cannot get value when an error exists"); +#endif +} + +#if LLVM_HAS_CXX11_STDLIB +ErrorOr<std::unique_ptr<int> > t3() { + return std::unique_ptr<int>(new int(3)); +} +#endif + +TEST(ErrorOr, Types) { + int x; + ErrorOr<int&> a(x); + *a = 42; + EXPECT_EQ(42, x); + + EXPECT_FALSE(ErrorOr<void>(errc::broken_pipe)); + EXPECT_TRUE(ErrorOr<void>(errc::success)); + +#if LLVM_HAS_CXX11_STDLIB + // Move only types. + EXPECT_EQ(3, **t3()); +#endif +} + +struct B {}; +struct D : B {}; + +TEST(ErrorOr, Covariant) { + ErrorOr<B*> b(ErrorOr<D*>(0)); + b = ErrorOr<D*>(0); + +#if LLVM_HAS_CXX11_STDLIB + ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(0)); + b1 = ErrorOr<std::unique_ptr<D> >(0); +#endif +} +} // end anon namespace + +struct InvalidArgError { + InvalidArgError() {} + InvalidArgError(std::string S) : ArgName(S) {} + std::string ArgName; +}; + +namespace llvm { +template<> +struct ErrorOrUserDataTraits<InvalidArgError> : true_type { + static error_code error() { + return make_error_code(errc::invalid_argument); + } +}; +} // end namespace llvm + +ErrorOr<int> t4() { + return InvalidArgError("adena"); +} + +ErrorOr<void> t5() { + return InvalidArgError("pie"); +} + +namespace { +TEST(ErrorOr, UserErrorData) { + ErrorOr<int> a = t4(); + EXPECT_EQ(errc::invalid_argument, a); + EXPECT_EQ("adena", t4().getError<InvalidArgError>().ArgName); + + ErrorOr<void> b = t5(); + EXPECT_EQ(errc::invalid_argument, b); + EXPECT_EQ("pie", b.getError<InvalidArgError>().ArgName); +} +} // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index edd350a..80d7245 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -7,13 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/FileOutputBuffer.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/PathV2.h" #include "llvm/Support/raw_ostream.h" - #include "gtest/gtest.h" using namespace llvm; @@ -27,13 +26,6 @@ using namespace llvm::sys; } else {} namespace { - - -// NOTE: Temporarily run this test on unix only. Once the file mapping -// routines are ported to Windows, this conditional can be removed. -#if LLVM_ON_UNIX - - TEST(FileOutputBuffer, Test) { // Create unique temporary directory for these tests SmallString<128> TestDirectory; @@ -45,7 +37,7 @@ TEST(FileOutputBuffer, Test) { ::close(fd); TestDirectory = path::parent_path(TestDirectory); } - + // TEST 1: Verify commit case. SmallString<128> File1(TestDirectory); File1.append("/file1"); @@ -61,7 +53,7 @@ TEST(FileOutputBuffer, Test) { } // Verify file exists and starts with special header. bool MagicMatches = false; - ASSERT_NO_ERROR(fs::has_magic(Twine(File1), Twine("AABBCCDDEEFFGGHHIIJJ"), + ASSERT_NO_ERROR(fs::has_magic(Twine(File1), Twine("AABBCCDDEEFFGGHHIIJJ"), MagicMatches)); EXPECT_TRUE(MagicMatches); // Verify file is correct size. @@ -82,8 +74,7 @@ TEST(FileOutputBuffer, Test) { // Verify file does not exist (because buffer not commited). bool Exists = false; ASSERT_NO_ERROR(fs::exists(Twine(File2), Exists)); - EXPECT_FALSE(Exists); - + EXPECT_FALSE(Exists); // TEST 3: Verify sizing down case. SmallString<128> File3(TestDirectory); @@ -100,7 +91,7 @@ TEST(FileOutputBuffer, Test) { } // Verify file exists and starts with special header. bool MagicMatches3 = false; - ASSERT_NO_ERROR(fs::has_magic(Twine(File3), Twine("AABBCCDDEEFFGGHHIIJJ"), + ASSERT_NO_ERROR(fs::has_magic(Twine(File3), Twine("AABBCCDDEEFFGGHHIIJJ"), MagicMatches3)); EXPECT_TRUE(MagicMatches3); // Verify file is correct size. @@ -108,13 +99,12 @@ TEST(FileOutputBuffer, Test) { ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size)); ASSERT_EQ(File3Size, 5000ULL); - // TEST 4: Verify file can be made executable. SmallString<128> File4(TestDirectory); File4.append("/file4"); { OwningPtr<FileOutputBuffer> Buffer; - ASSERT_NO_ERROR(FileOutputBuffer::create(File4, 8192, Buffer, + ASSERT_NO_ERROR(FileOutputBuffer::create(File4, 8192, Buffer, FileOutputBuffer::F_executable)); // Start buffer with special header. memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); @@ -131,7 +121,4 @@ TEST(FileOutputBuffer, Test) { uint32_t RemovedCount; ASSERT_NO_ERROR(fs::remove_all(TestDirectory.str(), RemovedCount)); } - -#endif // LLVM_ON_UNIX - } // anonymous namespace diff --git a/unittests/Support/IntegersSubsetTest.cpp b/unittests/Support/IntegersSubsetTest.cpp index 5d1dde4..f4298bf 100644 --- a/unittests/Support/IntegersSubsetTest.cpp +++ b/unittests/Support/IntegersSubsetTest.cpp @@ -7,12 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/APInt.h" #include "llvm/Support/IntegersSubset.h" +#include "llvm/ADT/APInt.h" #include "llvm/Support/IntegersSubsetMapping.h" - #include "gtest/gtest.h" - #include <vector> using namespace llvm; diff --git a/unittests/Support/ManagedStatic.cpp b/unittests/Support/ManagedStatic.cpp index bfeb0a7..8ddad38 100644 --- a/unittests/Support/ManagedStatic.cpp +++ b/unittests/Support/ManagedStatic.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Threading.h" #include "llvm/Config/config.h" +#include "llvm/Support/Threading.h" #ifdef HAVE_PTHREAD_H #include <pthread.h> #endif @@ -19,24 +19,41 @@ using namespace llvm; namespace { -#ifdef HAVE_PTHREAD_H +#if defined(HAVE_PTHREAD_H) && !__has_feature(memory_sanitizer) namespace test1 { llvm::ManagedStatic<int> ms; void *helper(void*) { *ms; return NULL; } + + // Valgrind's leak checker complains glibc's stack allocation. + // To appease valgrind, we provide our own stack for each thread. + void *allocate_stack(pthread_attr_t &a, size_t n = 65536) { + void *stack = malloc(n); + pthread_attr_init(&a); +#if defined(__linux__) + pthread_attr_setstack(&a, stack, n); +#endif + return stack; + } } TEST(Initialize, MultipleThreads) { // Run this test under tsan: http://code.google.com/p/data-race-test/ + pthread_attr_t a1, a2; + void *p1 = test1::allocate_stack(a1); + void *p2 = test1::allocate_stack(a2); + llvm_start_multithreaded(); pthread_t t1, t2; - pthread_create(&t1, NULL, test1::helper, NULL); - pthread_create(&t2, NULL, test1::helper, NULL); + pthread_create(&t1, &a1, test1::helper, NULL); + pthread_create(&t2, &a2, test1::helper, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); + free(p1); + free(p2); llvm_stop_multithreaded(); } #endif diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 6c78cd8..1d9f482 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -13,7 +13,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/ADT/OwningPtr.h" - #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/Support/MemoryTest.cpp b/unittests/Support/MemoryTest.cpp index 21cb27e..fae67a8 100644 --- a/unittests/Support/MemoryTest.cpp +++ b/unittests/Support/MemoryTest.cpp @@ -1,356 +1,357 @@ -//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator 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/Memory.h"
-#include "llvm/Support/Process.h"
-
-#include "gtest/gtest.h"
-#include <cstdlib>
-
-using namespace llvm;
-using namespace sys;
-
-namespace {
-
-class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
-public:
- MappedMemoryTest() {
- Flags = GetParam();
- PageSize = sys::Process::GetPageSize();
- }
-
-protected:
- // Adds RW flags to permit testing of the resulting memory
- unsigned getTestableEquivalent(unsigned RequestedFlags) {
- switch (RequestedFlags) {
- case Memory::MF_READ:
- case Memory::MF_WRITE:
- case Memory::MF_READ|Memory::MF_WRITE:
- return Memory::MF_READ|Memory::MF_WRITE;
- case Memory::MF_READ|Memory::MF_EXEC:
- case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
- case Memory::MF_EXEC:
- return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
- }
- // Default in case values are added to the enum, as required by some compilers
- return Memory::MF_READ|Memory::MF_WRITE;
- }
-
- // Returns true if the memory blocks overlap
- bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {
- if (M1.base() == M2.base())
- return true;
-
- if (M1.base() > M2.base())
- return (unsigned char *)M2.base() + M2.size() > M1.base();
-
- return (unsigned char *)M1.base() + M1.size() > M2.base();
- }
-
- unsigned Flags;
- size_t PageSize;
-};
-
-TEST_P(MappedMemoryTest, AllocAndRelease) {
- error_code EC;
- MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(sizeof(int), M1.size());
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
-}
-
-TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
- error_code EC;
- MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M2 = Memory::allocateMappedMemory(64, 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M3 = Memory::allocateMappedMemory(32, 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(16U, M1.size());
- EXPECT_NE((void*)0, M2.base());
- EXPECT_LE(64U, M2.size());
- EXPECT_NE((void*)0, M3.base());
- EXPECT_LE(32U, M3.size());
-
- EXPECT_FALSE(doesOverlap(M1, M2));
- EXPECT_FALSE(doesOverlap(M2, M3));
- EXPECT_FALSE(doesOverlap(M1, M3));
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));
- MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- EXPECT_NE((void*)0, M4.base());
- EXPECT_LE(16U, M4.size());
- EXPECT_FALSE(Memory::releaseMappedMemory(M4));
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));
-}
-
-TEST_P(MappedMemoryTest, BasicWrite) {
- // This test applies only to writeable combinations
- if (Flags && !(Flags & Memory::MF_WRITE))
- return;
-
- error_code EC;
- MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(sizeof(int), M1.size());
-
- int *a = (int*)M1.base();
- *a = 1;
- EXPECT_EQ(1, *a);
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
-}
-
-TEST_P(MappedMemoryTest, MultipleWrite) {
- // This test applies only to writeable combinations
- if (Flags && !(Flags & Memory::MF_WRITE))
- return;
- error_code EC;
- MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_FALSE(doesOverlap(M1, M2));
- EXPECT_FALSE(doesOverlap(M2, M3));
- EXPECT_FALSE(doesOverlap(M1, M3));
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(1U * sizeof(int), M1.size());
- EXPECT_NE((void*)0, M2.base());
- EXPECT_LE(8U * sizeof(int), M2.size());
- EXPECT_NE((void*)0, M3.base());
- EXPECT_LE(4U * sizeof(int), M3.size());
-
- int *x = (int*)M1.base();
- *x = 1;
-
- int *y = (int*)M2.base();
- for (int i = 0; i < 8; i++) {
- y[i] = i;
- }
-
- int *z = (int*)M3.base();
- *z = 42;
-
- EXPECT_EQ(1, *x);
- EXPECT_EQ(7, y[7]);
- EXPECT_EQ(42, *z);
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));
-
- MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- EXPECT_NE((void*)0, M4.base());
- EXPECT_LE(64U * sizeof(int), M4.size());
- x = (int*)M4.base();
- *x = 4;
- EXPECT_EQ(4, *x);
- EXPECT_FALSE(Memory::releaseMappedMemory(M4));
-
- // Verify that M2 remains unaffected by other activity
- for (int i = 0; i < 8; i++) {
- EXPECT_EQ(i, y[i]);
- }
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));
-}
-
-TEST_P(MappedMemoryTest, EnabledWrite) {
- error_code EC;
- MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(2U * sizeof(int), M1.size());
- EXPECT_NE((void*)0, M2.base());
- EXPECT_LE(8U * sizeof(int), M2.size());
- EXPECT_NE((void*)0, M3.base());
- EXPECT_LE(4U * sizeof(int), M3.size());
-
- EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
- EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
- EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
-
- EXPECT_FALSE(doesOverlap(M1, M2));
- EXPECT_FALSE(doesOverlap(M2, M3));
- EXPECT_FALSE(doesOverlap(M1, M3));
-
- int *x = (int*)M1.base();
- *x = 1;
- int *y = (int*)M2.base();
- for (unsigned int i = 0; i < 8; i++) {
- y[i] = i;
- }
- int *z = (int*)M3.base();
- *z = 42;
-
- EXPECT_EQ(1, *x);
- EXPECT_EQ(7, y[7]);
- EXPECT_EQ(42, *z);
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));
- EXPECT_EQ(6, y[6]);
-
- MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- EXPECT_NE((void*)0, M4.base());
- EXPECT_LE(16U, M4.size());
- EXPECT_EQ(error_code::success(), Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
- x = (int*)M4.base();
- *x = 4;
- EXPECT_EQ(4, *x);
- EXPECT_FALSE(Memory::releaseMappedMemory(M4));
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));
-}
-
-TEST_P(MappedMemoryTest, SuccessiveNear) {
- error_code EC;
- MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(16U, M1.size());
- EXPECT_NE((void*)0, M2.base());
- EXPECT_LE(64U, M2.size());
- EXPECT_NE((void*)0, M3.base());
- EXPECT_LE(32U, M3.size());
-
- EXPECT_FALSE(doesOverlap(M1, M2));
- EXPECT_FALSE(doesOverlap(M2, M3));
- EXPECT_FALSE(doesOverlap(M1, M3));
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));
-}
-
-TEST_P(MappedMemoryTest, DuplicateNear) {
- error_code EC;
- MemoryBlock Near((void*)(3*PageSize), 16);
- MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(16U, M1.size());
- EXPECT_NE((void*)0, M2.base());
- EXPECT_LE(64U, M2.size());
- EXPECT_NE((void*)0, M3.base());
- EXPECT_LE(32U, M3.size());
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));
-}
-
-TEST_P(MappedMemoryTest, ZeroNear) {
- error_code EC;
- MemoryBlock Near(0, 0);
- MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(16U, M1.size());
- EXPECT_NE((void*)0, M2.base());
- EXPECT_LE(64U, M2.size());
- EXPECT_NE((void*)0, M3.base());
- EXPECT_LE(32U, M3.size());
-
- EXPECT_FALSE(doesOverlap(M1, M2));
- EXPECT_FALSE(doesOverlap(M2, M3));
- EXPECT_FALSE(doesOverlap(M1, M3));
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));
-}
-
-TEST_P(MappedMemoryTest, ZeroSizeNear) {
- error_code EC;
- MemoryBlock Near((void*)(4*PageSize), 0);
- MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
- MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(16U, M1.size());
- EXPECT_NE((void*)0, M2.base());
- EXPECT_LE(64U, M2.size());
- EXPECT_NE((void*)0, M3.base());
- EXPECT_LE(32U, M3.size());
-
- EXPECT_FALSE(doesOverlap(M1, M2));
- EXPECT_FALSE(doesOverlap(M2, M3));
- EXPECT_FALSE(doesOverlap(M1, M3));
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));
-}
-
-TEST_P(MappedMemoryTest, UnalignedNear) {
- error_code EC;
- MemoryBlock Near((void*)(2*PageSize+5), 0);
- MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
- EXPECT_EQ(error_code::success(), EC);
-
- EXPECT_NE((void*)0, M1.base());
- EXPECT_LE(sizeof(int), M1.size());
-
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));
-}
-
-// Note that Memory::MF_WRITE is not supported exclusively across
-// operating systems and architectures and can imply MF_READ|MF_WRITE
-unsigned MemoryFlags[] = {
- Memory::MF_READ,
- Memory::MF_WRITE,
- Memory::MF_READ|Memory::MF_WRITE,
- Memory::MF_EXEC,
- Memory::MF_READ|Memory::MF_EXEC,
- Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
- };
-
-INSTANTIATE_TEST_CASE_P(AllocationTests,
- MappedMemoryTest,
- ::testing::ValuesIn(MemoryFlags));
-
-} // anonymous namespace
+//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator 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/Memory.h" +#include "llvm/Support/Process.h" +#include "gtest/gtest.h" +#include <cstdlib> + +using namespace llvm; +using namespace sys; + +namespace { + +class MappedMemoryTest : public ::testing::TestWithParam<unsigned> { +public: + MappedMemoryTest() { + Flags = GetParam(); + PageSize = sys::process::get_self()->page_size(); + } + +protected: + // Adds RW flags to permit testing of the resulting memory + unsigned getTestableEquivalent(unsigned RequestedFlags) { + switch (RequestedFlags) { + case Memory::MF_READ: + case Memory::MF_WRITE: + case Memory::MF_READ|Memory::MF_WRITE: + return Memory::MF_READ|Memory::MF_WRITE; + case Memory::MF_READ|Memory::MF_EXEC: + case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC: + case Memory::MF_EXEC: + return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC; + } + // Default in case values are added to the enum, as required by some compilers + return Memory::MF_READ|Memory::MF_WRITE; + } + + // Returns true if the memory blocks overlap + bool doesOverlap(MemoryBlock M1, MemoryBlock M2) { + if (M1.base() == M2.base()) + return true; + + if (M1.base() > M2.base()) + return (unsigned char *)M2.base() + M2.size() > M1.base(); + + return (unsigned char *)M1.base() + M1.size() > M2.base(); + } + + unsigned Flags; + size_t PageSize; +}; + +TEST_P(MappedMemoryTest, AllocAndRelease) { + error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(sizeof(int), M1.size()); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); +} + +TEST_P(MappedMemoryTest, MultipleAllocAndRelease) { + error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(64, 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(32, 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(16U, M1.size()); + EXPECT_NE((void*)0, M2.base()); + EXPECT_LE(64U, M2.size()); + EXPECT_NE((void*)0, M3.base()); + EXPECT_LE(32U, M3.size()); + + EXPECT_FALSE(doesOverlap(M1, M2)); + EXPECT_FALSE(doesOverlap(M2, M3)); + EXPECT_FALSE(doesOverlap(M1, M3)); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); + EXPECT_FALSE(Memory::releaseMappedMemory(M3)); + MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + EXPECT_NE((void*)0, M4.base()); + EXPECT_LE(16U, M4.size()); + EXPECT_FALSE(Memory::releaseMappedMemory(M4)); + EXPECT_FALSE(Memory::releaseMappedMemory(M2)); +} + +TEST_P(MappedMemoryTest, BasicWrite) { + // This test applies only to readable and writeable combinations + if (Flags && + !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE))) + return; + + error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(sizeof(int), M1.size()); + + int *a = (int*)M1.base(); + *a = 1; + EXPECT_EQ(1, *a); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); +} + +TEST_P(MappedMemoryTest, MultipleWrite) { + // This test applies only to readable and writeable combinations + if (Flags && + !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE))) + return; + error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_FALSE(doesOverlap(M1, M2)); + EXPECT_FALSE(doesOverlap(M2, M3)); + EXPECT_FALSE(doesOverlap(M1, M3)); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(1U * sizeof(int), M1.size()); + EXPECT_NE((void*)0, M2.base()); + EXPECT_LE(8U * sizeof(int), M2.size()); + EXPECT_NE((void*)0, M3.base()); + EXPECT_LE(4U * sizeof(int), M3.size()); + + int *x = (int*)M1.base(); + *x = 1; + + int *y = (int*)M2.base(); + for (int i = 0; i < 8; i++) { + y[i] = i; + } + + int *z = (int*)M3.base(); + *z = 42; + + EXPECT_EQ(1, *x); + EXPECT_EQ(7, y[7]); + EXPECT_EQ(42, *z); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); + EXPECT_FALSE(Memory::releaseMappedMemory(M3)); + + MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + EXPECT_NE((void*)0, M4.base()); + EXPECT_LE(64U * sizeof(int), M4.size()); + x = (int*)M4.base(); + *x = 4; + EXPECT_EQ(4, *x); + EXPECT_FALSE(Memory::releaseMappedMemory(M4)); + + // Verify that M2 remains unaffected by other activity + for (int i = 0; i < 8; i++) { + EXPECT_EQ(i, y[i]); + } + EXPECT_FALSE(Memory::releaseMappedMemory(M2)); +} + +TEST_P(MappedMemoryTest, EnabledWrite) { + error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(2U * sizeof(int), M1.size()); + EXPECT_NE((void*)0, M2.base()); + EXPECT_LE(8U * sizeof(int), M2.size()); + EXPECT_NE((void*)0, M3.base()); + EXPECT_LE(4U * sizeof(int), M3.size()); + + EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags))); + EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags))); + EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags))); + + EXPECT_FALSE(doesOverlap(M1, M2)); + EXPECT_FALSE(doesOverlap(M2, M3)); + EXPECT_FALSE(doesOverlap(M1, M3)); + + int *x = (int*)M1.base(); + *x = 1; + int *y = (int*)M2.base(); + for (unsigned int i = 0; i < 8; i++) { + y[i] = i; + } + int *z = (int*)M3.base(); + *z = 42; + + EXPECT_EQ(1, *x); + EXPECT_EQ(7, y[7]); + EXPECT_EQ(42, *z); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); + EXPECT_FALSE(Memory::releaseMappedMemory(M3)); + EXPECT_EQ(6, y[6]); + + MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + EXPECT_NE((void*)0, M4.base()); + EXPECT_LE(16U, M4.size()); + EXPECT_EQ(error_code::success(), Memory::protectMappedMemory(M4, getTestableEquivalent(Flags))); + x = (int*)M4.base(); + *x = 4; + EXPECT_EQ(4, *x); + EXPECT_FALSE(Memory::releaseMappedMemory(M4)); + EXPECT_FALSE(Memory::releaseMappedMemory(M2)); +} + +TEST_P(MappedMemoryTest, SuccessiveNear) { + error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(16U, M1.size()); + EXPECT_NE((void*)0, M2.base()); + EXPECT_LE(64U, M2.size()); + EXPECT_NE((void*)0, M3.base()); + EXPECT_LE(32U, M3.size()); + + EXPECT_FALSE(doesOverlap(M1, M2)); + EXPECT_FALSE(doesOverlap(M2, M3)); + EXPECT_FALSE(doesOverlap(M1, M3)); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); + EXPECT_FALSE(Memory::releaseMappedMemory(M3)); + EXPECT_FALSE(Memory::releaseMappedMemory(M2)); +} + +TEST_P(MappedMemoryTest, DuplicateNear) { + error_code EC; + MemoryBlock Near((void*)(3*PageSize), 16); + MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(16U, M1.size()); + EXPECT_NE((void*)0, M2.base()); + EXPECT_LE(64U, M2.size()); + EXPECT_NE((void*)0, M3.base()); + EXPECT_LE(32U, M3.size()); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); + EXPECT_FALSE(Memory::releaseMappedMemory(M3)); + EXPECT_FALSE(Memory::releaseMappedMemory(M2)); +} + +TEST_P(MappedMemoryTest, ZeroNear) { + error_code EC; + MemoryBlock Near(0, 0); + MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(16U, M1.size()); + EXPECT_NE((void*)0, M2.base()); + EXPECT_LE(64U, M2.size()); + EXPECT_NE((void*)0, M3.base()); + EXPECT_LE(32U, M3.size()); + + EXPECT_FALSE(doesOverlap(M1, M2)); + EXPECT_FALSE(doesOverlap(M2, M3)); + EXPECT_FALSE(doesOverlap(M1, M3)); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); + EXPECT_FALSE(Memory::releaseMappedMemory(M3)); + EXPECT_FALSE(Memory::releaseMappedMemory(M2)); +} + +TEST_P(MappedMemoryTest, ZeroSizeNear) { + error_code EC; + MemoryBlock Near((void*)(4*PageSize), 0); + MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(16U, M1.size()); + EXPECT_NE((void*)0, M2.base()); + EXPECT_LE(64U, M2.size()); + EXPECT_NE((void*)0, M3.base()); + EXPECT_LE(32U, M3.size()); + + EXPECT_FALSE(doesOverlap(M1, M2)); + EXPECT_FALSE(doesOverlap(M2, M3)); + EXPECT_FALSE(doesOverlap(M1, M3)); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); + EXPECT_FALSE(Memory::releaseMappedMemory(M3)); + EXPECT_FALSE(Memory::releaseMappedMemory(M2)); +} + +TEST_P(MappedMemoryTest, UnalignedNear) { + error_code EC; + MemoryBlock Near((void*)(2*PageSize+5), 0); + MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC); + EXPECT_EQ(error_code::success(), EC); + + EXPECT_NE((void*)0, M1.base()); + EXPECT_LE(sizeof(int), M1.size()); + + EXPECT_FALSE(Memory::releaseMappedMemory(M1)); +} + +// Note that Memory::MF_WRITE is not supported exclusively across +// operating systems and architectures and can imply MF_READ|MF_WRITE +unsigned MemoryFlags[] = { + Memory::MF_READ, + Memory::MF_WRITE, + Memory::MF_READ|Memory::MF_WRITE, + Memory::MF_EXEC, + Memory::MF_READ|Memory::MF_EXEC, + Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC + }; + +INSTANTIATE_TEST_CASE_P(AllocationTests, + MappedMemoryTest, + ::testing::ValuesIn(MemoryFlags)); + +} // anonymous namespace diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 63c9ae0..4511259 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -7,11 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/FileSystem.h" #include "llvm/Support/PathV2.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" - #include "gtest/gtest.h" using namespace llvm; @@ -225,6 +224,18 @@ TEST_F(FileSystemTest, TempFiles) { // Make sure Temp1 doesn't exist. ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists)); EXPECT_FALSE(TempFileExists); + +#ifdef LLVM_ON_WIN32 + // Path name > 260 chars should get an error. + const char *Path270 = + "abcdefghijklmnopqrstuvwxyz9abcdefghijklmnopqrstuvwxyz8" + "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" + "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" + "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" + "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; + EXPECT_EQ(fs::unique_file(Twine(Path270), FileDescriptor, TempPath), + windows_error::path_not_found); +#endif } TEST_F(FileSystemTest, DirectoryIteration) { @@ -351,6 +362,7 @@ TEST_F(FileSystemTest, FileMapping) { StringRef Val("hello there"); { fs::mapped_file_region mfr(FileDescriptor, + true, fs::mapped_file_region::readwrite, 4096, 0, @@ -375,7 +387,7 @@ TEST_F(FileSystemTest, FileMapping) { // Unmap temp file -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES fs::mapped_file_region m(Twine(TempPath), fs::mapped_file_region::readonly, 0, diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp new file mode 100644 index 0000000..e57c0e6 --- /dev/null +++ b/unittests/Support/ProcessTest.cpp @@ -0,0 +1,42 @@ +//===- unittest/Support/ProcessTest.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/Process.h" +#include "gtest/gtest.h" + +#ifdef LLVM_ON_WIN32 +#include "windows.h" +#endif + +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(GetCurrentProcess(), 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()); +} + +} // end anonymous namespace diff --git a/unittests/Support/RegexTest.cpp b/unittests/Support/RegexTest.cpp index 65b66c3..3577d10 100644 --- a/unittests/Support/RegexTest.cpp +++ b/unittests/Support/RegexTest.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "gtest/gtest.h" #include "llvm/Support/Regex.h" #include "llvm/ADT/SmallVector.h" +#include "gtest/gtest.h" #include <cstring> using namespace llvm; @@ -51,7 +51,6 @@ TEST_F(RegexTest, Basics) { EXPECT_EQ(1u, Matches.size()); EXPECT_EQ(String, Matches[0].str()); - std::string NulPattern="X[0-9]+X([a-f])?:([0-9]+)"; String="YX99a:513b"; NulPattern[7] = '\0'; @@ -62,6 +61,28 @@ TEST_F(RegexTest, Basics) { EXPECT_TRUE(r5.match(String)); } +TEST_F(RegexTest, Backreferences) { + Regex r1("([a-z]+)_\\1"); + SmallVector<StringRef, 4> Matches; + EXPECT_TRUE(r1.match("abc_abc", &Matches)); + EXPECT_EQ(2u, Matches.size()); + EXPECT_FALSE(r1.match("abc_ab", &Matches)); + + Regex r2("a([0-9])b\\1c\\1"); + EXPECT_TRUE(r2.match("a4b4c4", &Matches)); + EXPECT_EQ(2u, Matches.size()); + EXPECT_EQ("4", Matches[1].str()); + EXPECT_FALSE(r2.match("a2b2c3")); + + Regex r3("a([0-9])([a-z])b\\1\\2"); + EXPECT_TRUE(r3.match("a6zb6z", &Matches)); + EXPECT_EQ(3u, Matches.size()); + EXPECT_EQ("6", Matches[1].str()); + EXPECT_EQ("z", Matches[2].str()); + EXPECT_FALSE(r3.match("a6zb6y")); + EXPECT_FALSE(r3.match("a6zb7z")); +} + TEST_F(RegexTest, Substitution) { std::string Error; diff --git a/unittests/Support/ValueHandleTest.cpp b/unittests/Support/ValueHandleTest.cpp index 2e5e5b1..05aafa2 100644 --- a/unittests/Support/ValueHandleTest.cpp +++ b/unittests/Support/ValueHandleTest.cpp @@ -8,14 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ValueHandle.h" - -#include "llvm/Constants.h" -#include "llvm/Instructions.h" -#include "llvm/LLVMContext.h" #include "llvm/ADT/OwningPtr.h" - +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" #include "gtest/gtest.h" - #include <memory> using namespace llvm; diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp new file mode 100644 index 0000000..0993d8c --- /dev/null +++ b/unittests/Support/YAMLIOTest.cpp @@ -0,0 +1,1299 @@ +//===- unittest/Support/YAMLIOTest.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/YAMLTraits.h" +#include "gtest/gtest.h" + + +using llvm::yaml::Input; +using llvm::yaml::Output; +using llvm::yaml::IO; +using llvm::yaml::MappingTraits; +using llvm::yaml::MappingNormalization; +using llvm::yaml::ScalarTraits; +using llvm::yaml::Hex8; +using llvm::yaml::Hex16; +using llvm::yaml::Hex32; +using llvm::yaml::Hex64; + + +//===----------------------------------------------------------------------===// +// Test MappingTraits +//===----------------------------------------------------------------------===// + +struct FooBar { + int foo; + int bar; +}; +typedef std::vector<FooBar> FooBarSequence; + +LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar) + + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<FooBar> { + static void mapping(IO &io, FooBar& fb) { + io.mapRequired("foo", fb.foo); + io.mapRequired("bar", fb.bar); + } + }; +} +} + + +// +// Test the reading of a yaml mapping +// +TEST(YAMLIO, TestMapRead) { + FooBar doc; + Input yin("---\nfoo: 3\nbar: 5\n...\n"); + yin >> doc; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(doc.foo, 3); + EXPECT_EQ(doc.bar,5); +} + + +// +// Test the reading of a yaml sequence of mappings +// +TEST(YAMLIO, TestSequenceMapRead) { + FooBarSequence seq; + Input yin("---\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n"); + yin >> seq; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(seq.size(), 2UL); + FooBar& map1 = seq[0]; + FooBar& map2 = seq[1]; + EXPECT_EQ(map1.foo, 3); + EXPECT_EQ(map1.bar, 5); + EXPECT_EQ(map2.foo, 7); + EXPECT_EQ(map2.bar, 9); +} + + +// +// Test writing then reading back a sequence of mappings +// +TEST(YAMLIO, TestSequenceMapWriteAndRead) { + std::string intermediate; + { + FooBar entry1; + entry1.foo = 10; + entry1.bar = -3; + FooBar entry2; + entry2.foo = 257; + entry2.bar = 0; + FooBarSequence seq; + seq.push_back(entry1); + seq.push_back(entry2); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << seq; + } + + { + Input yin(intermediate); + FooBarSequence seq2; + yin >> seq2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(seq2.size(), 2UL); + FooBar& map1 = seq2[0]; + FooBar& map2 = seq2[1]; + EXPECT_EQ(map1.foo, 10); + EXPECT_EQ(map1.bar, -3); + EXPECT_EQ(map2.foo, 257); + EXPECT_EQ(map2.bar, 0); + } +} + + +//===----------------------------------------------------------------------===// +// Test built-in types +//===----------------------------------------------------------------------===// + +struct BuiltInTypes { + llvm::StringRef str; + uint64_t u64; + uint32_t u32; + uint16_t u16; + uint8_t u8; + bool b; + int64_t s64; + int32_t s32; + int16_t s16; + int8_t s8; + float f; + double d; + Hex8 h8; + Hex16 h16; + Hex32 h32; + Hex64 h64; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<BuiltInTypes> { + static void mapping(IO &io, BuiltInTypes& bt) { + io.mapRequired("str", bt.str); + io.mapRequired("u64", bt.u64); + io.mapRequired("u32", bt.u32); + io.mapRequired("u16", bt.u16); + io.mapRequired("u8", bt.u8); + io.mapRequired("b", bt.b); + io.mapRequired("s64", bt.s64); + io.mapRequired("s32", bt.s32); + io.mapRequired("s16", bt.s16); + io.mapRequired("s8", bt.s8); + io.mapRequired("f", bt.f); + io.mapRequired("d", bt.d); + io.mapRequired("h8", bt.h8); + io.mapRequired("h16", bt.h16); + io.mapRequired("h32", bt.h32); + io.mapRequired("h64", bt.h64); + } + }; +} +} + + +// +// Test the reading of all built-in scalar conversions +// +TEST(YAMLIO, TestReadBuiltInTypes) { + BuiltInTypes map; + Input yin("---\n" + "str: hello there\n" + "u64: 5000000000\n" + "u32: 4000000000\n" + "u16: 65000\n" + "u8: 255\n" + "b: false\n" + "s64: -5000000000\n" + "s32: -2000000000\n" + "s16: -32000\n" + "s8: -127\n" + "f: 137.125\n" + "d: -2.8625\n" + "h8: 0xFF\n" + "h16: 0x8765\n" + "h32: 0xFEDCBA98\n" + "h64: 0xFEDCBA9876543210\n" + "...\n"); + yin >> map; + + EXPECT_FALSE(yin.error()); + EXPECT_TRUE(map.str.equals("hello there")); + EXPECT_EQ(map.u64, 5000000000ULL); + EXPECT_EQ(map.u32, 4000000000U); + EXPECT_EQ(map.u16, 65000); + EXPECT_EQ(map.u8, 255); + EXPECT_EQ(map.b, false); + EXPECT_EQ(map.s64, -5000000000LL); + EXPECT_EQ(map.s32, -2000000000L); + EXPECT_EQ(map.s16, -32000); + EXPECT_EQ(map.s8, -127); + EXPECT_EQ(map.f, 137.125); + EXPECT_EQ(map.d, -2.8625); + EXPECT_EQ(map.h8, Hex8(255)); + EXPECT_EQ(map.h16, Hex16(0x8765)); + EXPECT_EQ(map.h32, Hex32(0xFEDCBA98)); + EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL)); +} + + +// +// Test writing then reading back all built-in scalar types +// +TEST(YAMLIO, TestReadWriteBuiltInTypes) { + std::string intermediate; + { + BuiltInTypes map; + map.str = "one two"; + map.u64 = 6000000000ULL; + map.u32 = 3000000000U; + map.u16 = 50000; + map.u8 = 254; + map.b = true; + map.s64 = -6000000000LL; + map.s32 = -2000000000; + map.s16 = -32000; + map.s8 = -128; + map.f = 3.25; + map.d = -2.8625; + map.h8 = 254; + map.h16 = 50000; + map.h32 = 3000000000U; + map.h64 = 6000000000LL; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + } + + { + Input yin(intermediate); + BuiltInTypes map; + yin >> map; + + EXPECT_FALSE(yin.error()); + EXPECT_TRUE(map.str.equals("one two")); + EXPECT_EQ(map.u64, 6000000000ULL); + EXPECT_EQ(map.u32, 3000000000U); + EXPECT_EQ(map.u16, 50000); + EXPECT_EQ(map.u8, 254); + EXPECT_EQ(map.b, true); + EXPECT_EQ(map.s64, -6000000000LL); + EXPECT_EQ(map.s32, -2000000000L); + EXPECT_EQ(map.s16, -32000); + EXPECT_EQ(map.s8, -128); + EXPECT_EQ(map.f, 3.25); + EXPECT_EQ(map.d, -2.8625); + EXPECT_EQ(map.h8, Hex8(254)); + EXPECT_EQ(map.h16, Hex16(50000)); + EXPECT_EQ(map.h32, Hex32(3000000000U)); + EXPECT_EQ(map.h64, Hex64(6000000000LL)); + } +} + + + +//===----------------------------------------------------------------------===// +// Test ScalarEnumerationTraits +//===----------------------------------------------------------------------===// + +enum Colors { + cRed, + cBlue, + cGreen, + cYellow +}; + +struct ColorMap { + Colors c1; + Colors c2; + Colors c3; + Colors c4; + Colors c5; + Colors c6; +}; + +namespace llvm { +namespace yaml { + template <> + struct ScalarEnumerationTraits<Colors> { + static void enumeration(IO &io, Colors &value) { + io.enumCase(value, "red", cRed); + io.enumCase(value, "blue", cBlue); + io.enumCase(value, "green", cGreen); + io.enumCase(value, "yellow",cYellow); + } + }; + template <> + struct MappingTraits<ColorMap> { + static void mapping(IO &io, ColorMap& c) { + io.mapRequired("c1", c.c1); + io.mapRequired("c2", c.c2); + io.mapRequired("c3", c.c3); + io.mapOptional("c4", c.c4, cBlue); // supplies default + io.mapOptional("c5", c.c5, cYellow); // supplies default + io.mapOptional("c6", c.c6, cRed); // supplies default + } + }; +} +} + + +// +// Test reading enumerated scalars +// +TEST(YAMLIO, TestEnumRead) { + ColorMap map; + Input yin("---\n" + "c1: blue\n" + "c2: red\n" + "c3: green\n" + "c5: yellow\n" + "...\n"); + yin >> map; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cBlue, map.c1); + EXPECT_EQ(cRed, map.c2); + EXPECT_EQ(cGreen, map.c3); + EXPECT_EQ(cBlue, map.c4); // tests default + EXPECT_EQ(cYellow,map.c5); // tests overridden + EXPECT_EQ(cRed, map.c6); // tests default +} + + + +//===----------------------------------------------------------------------===// +// Test ScalarBitSetTraits +//===----------------------------------------------------------------------===// + +enum MyFlags { + flagNone = 0, + flagBig = 1 << 0, + flagFlat = 1 << 1, + flagRound = 1 << 2, + flagPointy = 1 << 3 +}; +inline MyFlags operator|(MyFlags a, MyFlags b) { + return static_cast<MyFlags>( + static_cast<uint32_t>(a) | static_cast<uint32_t>(b)); +} + +struct FlagsMap { + MyFlags f1; + MyFlags f2; + MyFlags f3; + MyFlags f4; +}; + + +namespace llvm { +namespace yaml { + template <> + struct ScalarBitSetTraits<MyFlags> { + static void bitset(IO &io, MyFlags &value) { + io.bitSetCase(value, "big", flagBig); + io.bitSetCase(value, "flat", flagFlat); + io.bitSetCase(value, "round", flagRound); + io.bitSetCase(value, "pointy",flagPointy); + } + }; + template <> + struct MappingTraits<FlagsMap> { + static void mapping(IO &io, FlagsMap& c) { + io.mapRequired("f1", c.f1); + io.mapRequired("f2", c.f2); + io.mapRequired("f3", c.f3); + io.mapOptional("f4", c.f4, MyFlags(flagRound)); + } + }; +} +} + + +// +// Test reading flow sequence representing bit-mask values +// +TEST(YAMLIO, TestFlagsRead) { + FlagsMap map; + Input yin("---\n" + "f1: [ big ]\n" + "f2: [ round, flat ]\n" + "f3: []\n" + "...\n"); + yin >> map; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(flagBig, map.f1); + EXPECT_EQ(flagRound|flagFlat, map.f2); + EXPECT_EQ(flagNone, map.f3); // check empty set + EXPECT_EQ(flagRound, map.f4); // check optional key +} + + +// +// Test writing then reading back bit-mask values +// +TEST(YAMLIO, TestReadWriteFlags) { + std::string intermediate; + { + FlagsMap map; + map.f1 = flagBig; + map.f2 = flagRound | flagFlat; + map.f3 = flagNone; + map.f4 = flagNone; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + } + + { + Input yin(intermediate); + FlagsMap map2; + yin >> map2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(flagBig, map2.f1); + EXPECT_EQ(flagRound|flagFlat, map2.f2); + EXPECT_EQ(flagNone, map2.f3); + //EXPECT_EQ(flagRound, map2.f4); // check optional key + } +} + + + +//===----------------------------------------------------------------------===// +// Test ScalarTraits +//===----------------------------------------------------------------------===// + +struct MyCustomType { + int length; + int width; +}; + +struct MyCustomTypeMap { + MyCustomType f1; + MyCustomType f2; + int f3; +}; + + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<MyCustomTypeMap> { + static void mapping(IO &io, MyCustomTypeMap& s) { + io.mapRequired("f1", s.f1); + io.mapRequired("f2", s.f2); + io.mapRequired("f3", s.f3); + } + }; + // MyCustomType is formatted as a yaml scalar. A value of + // {length=3, width=4} would be represented in yaml as "3 by 4". + template<> + struct ScalarTraits<MyCustomType> { + static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) { + out << llvm::format("%d by %d", value.length, value.width); + } + static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) { + size_t byStart = scalar.find("by"); + if ( byStart != StringRef::npos ) { + StringRef lenStr = scalar.slice(0, byStart); + lenStr = lenStr.rtrim(); + if ( lenStr.getAsInteger(0, value.length) ) { + return "malformed length"; + } + StringRef widthStr = scalar.drop_front(byStart+2); + widthStr = widthStr.ltrim(); + if ( widthStr.getAsInteger(0, value.width) ) { + return "malformed width"; + } + return StringRef(); + } + else { + return "malformed by"; + } + } + }; +} +} + + +// +// Test writing then reading back custom values +// +TEST(YAMLIO, TestReadWriteMyCustomType) { + std::string intermediate; + { + MyCustomTypeMap map; + map.f1.length = 1; + map.f1.width = 4; + map.f2.length = 100; + map.f2.width = 400; + map.f3 = 10; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + } + + { + Input yin(intermediate); + MyCustomTypeMap map2; + yin >> map2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(1, map2.f1.length); + EXPECT_EQ(4, map2.f1.width); + EXPECT_EQ(100, map2.f2.length); + EXPECT_EQ(400, map2.f2.width); + EXPECT_EQ(10, map2.f3); + } +} + + +//===----------------------------------------------------------------------===// +// Test flow sequences +//===----------------------------------------------------------------------===// + +LLVM_YAML_STRONG_TYPEDEF(int, MyNumber) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef) + +namespace llvm { +namespace yaml { + template<> + struct ScalarTraits<MyNumber> { + static void output(const MyNumber &value, void *, llvm::raw_ostream &out) { + out << value; + } + + static StringRef input(StringRef scalar, void *, MyNumber &value) { + long long n; + if ( getAsSignedInteger(scalar, 0, n) ) + return "invalid number"; + value = n; + return StringRef(); + } + }; +} +} + +struct NameAndNumbers { + llvm::StringRef name; + std::vector<llvm::StringRef> strings; + std::vector<MyNumber> single; + std::vector<MyNumber> numbers; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<NameAndNumbers> { + static void mapping(IO &io, NameAndNumbers& nn) { + io.mapRequired("name", nn.name); + io.mapRequired("strings", nn.strings); + io.mapRequired("single", nn.single); + io.mapRequired("numbers", nn.numbers); + } + }; +} +} + + +// +// Test writing then reading back custom values +// +TEST(YAMLIO, TestReadWriteMyFlowSequence) { + std::string intermediate; + { + NameAndNumbers map; + map.name = "hello"; + map.strings.push_back(llvm::StringRef("one")); + map.strings.push_back(llvm::StringRef("two")); + map.single.push_back(1); + map.numbers.push_back(10); + map.numbers.push_back(-30); + map.numbers.push_back(1024); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + + // Verify sequences were written in flow style + ostr.flush(); + llvm::StringRef flowOut(intermediate); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024")); + } + + { + Input yin(intermediate); + NameAndNumbers map2; + yin >> map2; + + EXPECT_FALSE(yin.error()); + EXPECT_TRUE(map2.name.equals("hello")); + EXPECT_EQ(map2.strings.size(), 2UL); + EXPECT_TRUE(map2.strings[0].equals("one")); + EXPECT_TRUE(map2.strings[1].equals("two")); + EXPECT_EQ(map2.single.size(), 1UL); + EXPECT_EQ(1, map2.single[0]); + EXPECT_EQ(map2.numbers.size(), 3UL); + EXPECT_EQ(10, map2.numbers[0]); + EXPECT_EQ(-30, map2.numbers[1]); + EXPECT_EQ(1024, map2.numbers[2]); + } +} + + +//===----------------------------------------------------------------------===// +// Test normalizing/denormalizing +//===----------------------------------------------------------------------===// + +LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds) + +typedef std::vector<TotalSeconds> SecondsSequence; + +LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds) + + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<TotalSeconds> { + + class NormalizedSeconds { + public: + NormalizedSeconds(IO &io) + : hours(0), minutes(0), seconds(0) { + } + NormalizedSeconds(IO &, TotalSeconds &secs) + : hours(secs/3600), + minutes((secs - (hours*3600))/60), + seconds(secs % 60) { + } + TotalSeconds denormalize(IO &) { + return TotalSeconds(hours*3600 + minutes*60 + seconds); + } + + uint32_t hours; + uint8_t minutes; + uint8_t seconds; + }; + + static void mapping(IO &io, TotalSeconds &secs) { + MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs); + + io.mapOptional("hours", keys->hours, (uint32_t)0); + io.mapOptional("minutes", keys->minutes, (uint8_t)0); + io.mapRequired("seconds", keys->seconds); + } + }; +} +} + + +// +// Test the reading of a yaml sequence of mappings +// +TEST(YAMLIO, TestReadMySecondsSequence) { + SecondsSequence seq; + Input yin("---\n - hours: 1\n seconds: 5\n - seconds: 59\n...\n"); + yin >> seq; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(seq.size(), 2UL); + EXPECT_EQ(seq[0], 3605U); + EXPECT_EQ(seq[1], 59U); +} + + +// +// Test writing then reading back custom values +// +TEST(YAMLIO, TestReadWriteMySecondsSequence) { + std::string intermediate; + { + SecondsSequence seq; + seq.push_back(4000); + seq.push_back(500); + seq.push_back(59); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << seq; + } + { + Input yin(intermediate); + SecondsSequence seq2; + yin >> seq2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(seq2.size(), 3UL); + EXPECT_EQ(seq2[0], 4000U); + EXPECT_EQ(seq2[1], 500U); + EXPECT_EQ(seq2[2], 59U); + } +} + + +//===----------------------------------------------------------------------===// +// Test dynamic typing +//===----------------------------------------------------------------------===// + +enum AFlags { + a1, + a2, + a3 +}; + +enum BFlags { + b1, + b2, + b3 +}; + +enum Kind { + kindA, + kindB +}; + +struct KindAndFlags { + KindAndFlags() : kind(kindA), flags(0) { } + KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { } + Kind kind; + uint32_t flags; +}; + +typedef std::vector<KindAndFlags> KindAndFlagsSequence; + +LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags) + +namespace llvm { +namespace yaml { + template <> + struct ScalarEnumerationTraits<AFlags> { + static void enumeration(IO &io, AFlags &value) { + io.enumCase(value, "a1", a1); + io.enumCase(value, "a2", a2); + io.enumCase(value, "a3", a3); + } + }; + template <> + struct ScalarEnumerationTraits<BFlags> { + static void enumeration(IO &io, BFlags &value) { + io.enumCase(value, "b1", b1); + io.enumCase(value, "b2", b2); + io.enumCase(value, "b3", b3); + } + }; + template <> + struct ScalarEnumerationTraits<Kind> { + static void enumeration(IO &io, Kind &value) { + io.enumCase(value, "A", kindA); + io.enumCase(value, "B", kindB); + } + }; + template <> + struct MappingTraits<KindAndFlags> { + static void mapping(IO &io, KindAndFlags& kf) { + io.mapRequired("kind", kf.kind); + // Type of "flags" field varies depending on "kind" field. + // Use memcpy here to avoid breaking strict aliasing rules. + if (kf.kind == kindA) { + AFlags aflags = static_cast<AFlags>(kf.flags); + io.mapRequired("flags", aflags); + kf.flags = aflags; + } else { + BFlags bflags = static_cast<BFlags>(kf.flags); + io.mapRequired("flags", bflags); + kf.flags = bflags; + } + } + }; +} +} + + +// +// Test the reading of a yaml sequence dynamic types +// +TEST(YAMLIO, TestReadKindAndFlagsSequence) { + KindAndFlagsSequence seq; + Input yin("---\n - kind: A\n flags: a2\n - kind: B\n flags: b1\n...\n"); + yin >> seq; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(seq.size(), 2UL); + EXPECT_EQ(seq[0].kind, kindA); + EXPECT_EQ(seq[0].flags, (uint32_t)a2); + EXPECT_EQ(seq[1].kind, kindB); + EXPECT_EQ(seq[1].flags, (uint32_t)b1); +} + +// +// Test writing then reading back dynamic types +// +TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) { + std::string intermediate; + { + KindAndFlagsSequence seq; + seq.push_back(KindAndFlags(kindA,a1)); + seq.push_back(KindAndFlags(kindB,b1)); + seq.push_back(KindAndFlags(kindA,a2)); + seq.push_back(KindAndFlags(kindB,b2)); + seq.push_back(KindAndFlags(kindA,a3)); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << seq; + } + { + Input yin(intermediate); + KindAndFlagsSequence seq2; + yin >> seq2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(seq2.size(), 5UL); + EXPECT_EQ(seq2[0].kind, kindA); + EXPECT_EQ(seq2[0].flags, (uint32_t)a1); + EXPECT_EQ(seq2[1].kind, kindB); + EXPECT_EQ(seq2[1].flags, (uint32_t)b1); + EXPECT_EQ(seq2[2].kind, kindA); + EXPECT_EQ(seq2[2].flags, (uint32_t)a2); + EXPECT_EQ(seq2[3].kind, kindB); + EXPECT_EQ(seq2[3].flags, (uint32_t)b2); + EXPECT_EQ(seq2[4].kind, kindA); + EXPECT_EQ(seq2[4].flags, (uint32_t)a3); + } +} + + +//===----------------------------------------------------------------------===// +// Test document list +//===----------------------------------------------------------------------===// + +struct FooBarMap { + int foo; + int bar; +}; +typedef std::vector<FooBarMap> FooBarMapDocumentList; + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap) + + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<FooBarMap> { + static void mapping(IO &io, FooBarMap& fb) { + io.mapRequired("foo", fb.foo); + io.mapRequired("bar", fb.bar); + } + }; +} +} + + +// +// Test the reading of a yaml mapping +// +TEST(YAMLIO, TestDocRead) { + FooBarMap doc; + Input yin("---\nfoo: 3\nbar: 5\n...\n"); + yin >> doc; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(doc.foo, 3); + EXPECT_EQ(doc.bar,5); +} + + + +// +// Test writing then reading back a sequence of mappings +// +TEST(YAMLIO, TestSequenceDocListWriteAndRead) { + std::string intermediate; + { + FooBarMap doc1; + doc1.foo = 10; + doc1.bar = -3; + FooBarMap doc2; + doc2.foo = 257; + doc2.bar = 0; + std::vector<FooBarMap> docList; + docList.push_back(doc1); + docList.push_back(doc2); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << docList; + } + + + { + Input yin(intermediate); + std::vector<FooBarMap> docList2; + yin >> docList2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(docList2.size(), 2UL); + FooBarMap& map1 = docList2[0]; + FooBarMap& map2 = docList2[1]; + EXPECT_EQ(map1.foo, 10); + EXPECT_EQ(map1.bar, -3); + EXPECT_EQ(map2.foo, 257); + EXPECT_EQ(map2.bar, 0); + } +} + + +//===----------------------------------------------------------------------===// +// Test error handling +//===----------------------------------------------------------------------===// + + + +static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) { +} + + +// +// Test error handling of unknown enumerated scalar +// +TEST(YAMLIO, TestColorsReadError) { + ColorMap map; + Input yin("---\n" + "c1: blue\n" + "c2: purple\n" + "c3: green\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> map; + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling of flow sequence with unknown value +// +TEST(YAMLIO, TestFlagsReadError) { + FlagsMap map; + Input yin("---\n" + "f1: [ big ]\n" + "f2: [ round, hollow ]\n" + "f3: []\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> map; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in uint8_t type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t) +TEST(YAMLIO, TestReadBuiltInTypesUint8Error) { + std::vector<uint8_t> seq; + Input yin("---\n" + "- 255\n" + "- 0\n" + "- 257\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in uint16_t type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t) +TEST(YAMLIO, TestReadBuiltInTypesUint16Error) { + std::vector<uint16_t> seq; + Input yin("---\n" + "- 65535\n" + "- 0\n" + "- 66000\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in uint32_t type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t) +TEST(YAMLIO, TestReadBuiltInTypesUint32Error) { + std::vector<uint32_t> seq; + Input yin("---\n" + "- 4000000000\n" + "- 0\n" + "- 5000000000\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in uint64_t type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t) +TEST(YAMLIO, TestReadBuiltInTypesUint64Error) { + std::vector<uint64_t> seq; + Input yin("---\n" + "- 18446744073709551615\n" + "- 0\n" + "- 19446744073709551615\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in int8_t type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t) +TEST(YAMLIO, TestReadBuiltInTypesint8OverError) { + std::vector<int8_t> seq; + Input yin("---\n" + "- -128\n" + "- 0\n" + "- 127\n" + "- 128\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + +// +// Test error handling reading built-in int8_t type +// +TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) { + std::vector<int8_t> seq; + Input yin("---\n" + "- -128\n" + "- 0\n" + "- 127\n" + "- -129\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in int16_t type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t) +TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) { + std::vector<int16_t> seq; + Input yin("---\n" + "- 32767\n" + "- 0\n" + "- -32768\n" + "- -32769\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in int16_t type +// +TEST(YAMLIO, TestReadBuiltInTypesint16OverError) { + std::vector<int16_t> seq; + Input yin("---\n" + "- 32767\n" + "- 0\n" + "- -32768\n" + "- 32768\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in int32_t type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t) +TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) { + std::vector<int32_t> seq; + Input yin("---\n" + "- 2147483647\n" + "- 0\n" + "- -2147483648\n" + "- -2147483649\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + +// +// Test error handling reading built-in int32_t type +// +TEST(YAMLIO, TestReadBuiltInTypesint32OverError) { + std::vector<int32_t> seq; + Input yin("---\n" + "- 2147483647\n" + "- 0\n" + "- -2147483648\n" + "- 2147483649\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in int64_t type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t) +TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) { + std::vector<int64_t> seq; + Input yin("---\n" + "- -9223372036854775808\n" + "- 0\n" + "- 9223372036854775807\n" + "- -9223372036854775809\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + +// +// Test error handling reading built-in int64_t type +// +TEST(YAMLIO, TestReadBuiltInTypesint64OverError) { + std::vector<int64_t> seq; + Input yin("---\n" + "- -9223372036854775808\n" + "- 0\n" + "- 9223372036854775807\n" + "- 9223372036854775809\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + +// +// Test error handling reading built-in float type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(float) +TEST(YAMLIO, TestReadBuiltInTypesFloatError) { + std::vector<float> seq; + Input yin("---\n" + "- 0.0\n" + "- 1000.1\n" + "- -123.456\n" + "- 1.2.3\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + +// +// Test error handling reading built-in float type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(double) +TEST(YAMLIO, TestReadBuiltInTypesDoubleError) { + std::vector<double> seq; + Input yin("---\n" + "- 0.0\n" + "- 1000.1\n" + "- -123.456\n" + "- 1.2.3\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + +// +// Test error handling reading built-in Hex8 type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8) +TEST(YAMLIO, TestReadBuiltInTypesHex8Error) { + std::vector<Hex8> seq; + Input yin("---\n" + "- 0x12\n" + "- 0xFE\n" + "- 0x123\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + + +// +// Test error handling reading built-in Hex16 type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16) +TEST(YAMLIO, TestReadBuiltInTypesHex16Error) { + std::vector<Hex16> seq; + Input yin("---\n" + "- 0x0012\n" + "- 0xFEFF\n" + "- 0x12345\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + +// +// Test error handling reading built-in Hex32 type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32) +TEST(YAMLIO, TestReadBuiltInTypesHex32Error) { + std::vector<Hex32> seq; + Input yin("---\n" + "- 0x0012\n" + "- 0xFEFF0000\n" + "- 0x1234556789\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + +// +// Test error handling reading built-in Hex64 type +// +LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64) +TEST(YAMLIO, TestReadBuiltInTypesHex64Error) { + std::vector<Hex64> seq; + Input yin("---\n" + "- 0x0012\n" + "- 0xFFEEDDCCBBAA9988\n" + "- 0x12345567890ABCDEF0\n" + "...\n"); + yin.setDiagHandler(suppressErrorMessages); + yin >> seq; + + EXPECT_TRUE(yin.error()); +} + diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp index 480a573..e983935 100644 --- a/unittests/Support/YAMLParserTest.cpp +++ b/unittests/Support/YAMLParserTest.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" #include "gtest/gtest.h" @@ -21,6 +22,12 @@ static void SuppressDiagnosticsOutput(const SMDiagnostic &, void *) { // to reduce noise in unit test runs. } +// Assumes Ctx is an SMDiagnostic where Diag can be stored. +static void CollectDiagnosticsOutput(const SMDiagnostic &Diag, void *Ctx) { + SMDiagnostic* DiagOut = static_cast<SMDiagnostic*>(Ctx); + *DiagOut = Diag; +} + // Checks that the given input gives a parse error. Makes sure that an error // text is available and the parse fails. static void ExpectParseError(StringRef Message, StringRef Input) { @@ -182,4 +189,31 @@ TEST(YAMLParser, WorksWithIteratorAlgorithms) { EXPECT_EQ(6, std::distance(Array->begin(), Array->end())); } +TEST(YAMLParser, DefaultDiagnosticFilename) { + SourceMgr SM; + + SMDiagnostic GeneratedDiag; + SM.setDiagHandler(CollectDiagnosticsOutput, &GeneratedDiag); + + // When we construct a YAML stream over an unnamed string, + // the filename is hard-coded as "YAML". + yaml::Stream UnnamedStream("[]", SM); + UnnamedStream.printError(UnnamedStream.begin()->getRoot(), "Hello, World!"); + EXPECT_EQ("YAML", GeneratedDiag.getFilename()); +} + +TEST(YAMLParser, DiagnosticFilenameFromBufferID) { + SourceMgr SM; + + SMDiagnostic GeneratedDiag; + SM.setDiagHandler(CollectDiagnosticsOutput, &GeneratedDiag); + + // 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); + Stream.printError(Stream.begin()->getRoot(), "Hello, World!"); + EXPECT_EQ("buffername.yaml", GeneratedDiag.getFilename()); +} + } // end namespace llvm diff --git a/unittests/Support/formatted_raw_ostream_test.cpp b/unittests/Support/formatted_raw_ostream_test.cpp index 4725ced..9bb8046 100644 --- a/unittests/Support/formatted_raw_ostream_test.cpp +++ b/unittests/Support/formatted_raw_ostream_test.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "gtest/gtest.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/FormattedStream.h" +#include "gtest/gtest.h" using namespace llvm; |