diff options
Diffstat (limited to 'unittests/Support')
-rw-r--r-- | unittests/Support/AlignOfTest.cpp | 129 | ||||
-rw-r--r-- | unittests/Support/CMakeLists.txt | 5 | ||||
-rw-r--r-- | unittests/Support/Casting.cpp | 59 | ||||
-rw-r--r-- | unittests/Support/DataExtractorTest.cpp | 9 | ||||
-rw-r--r-- | unittests/Support/MemoryBufferTest.cpp | 99 | ||||
-rw-r--r-- | unittests/Support/MemoryTest.cpp | 356 | ||||
-rw-r--r-- | unittests/Support/formatted_raw_ostream_test.cpp | 33 |
7 files changed, 615 insertions, 75 deletions
diff --git a/unittests/Support/AlignOfTest.cpp b/unittests/Support/AlignOfTest.cpp index 6f57668..f01e660 100644 --- a/unittests/Support/AlignOfTest.cpp +++ b/unittests/Support/AlignOfTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/Support/AlignOfTest.cpp - Alignment utility tests ----===// +//=== - llvm/unittest/Support/AlignOfTest.cpp - Alignment utility tests ----===// // // The LLVM Compiler Infrastructure // @@ -23,31 +23,25 @@ namespace { #endif // Define some fixed alignment types to use in these tests. -#if __cplusplus == 201103L || __has_feature(cxx_alignas) -typedef char alignas(1) A1; -typedef char alignas(2) A2; -typedef char alignas(4) A4; -typedef char alignas(8) A8; -#elif defined(__clang__) || defined(__GNUC__) -typedef char A1 __attribute__((aligned(1))); -typedef char A2 __attribute__((aligned(2))); -typedef char A4 __attribute__((aligned(4))); -typedef char A8 __attribute__((aligned(8))); +#if __has_feature(cxx_alignas) +struct alignas(1) A1 { }; +struct alignas(2) A2 { }; +struct alignas(4) A4 { }; +struct alignas(8) A8 { }; +#elif defined(__GNUC__) +struct A1 { } __attribute__((aligned(1))); +struct A2 { } __attribute__((aligned(2))); +struct A4 { } __attribute__((aligned(4))); +struct A8 { } __attribute__((aligned(8))); #elif defined(_MSC_VER) -typedef __declspec(align(1)) char A1; -typedef __declspec(align(2)) char A2; -typedef __declspec(align(4)) char A4; -typedef __declspec(align(8)) char A8; +__declspec(align(1)) struct A1 { }; +__declspec(align(2)) struct A2 { }; +__declspec(align(4)) struct A4 { }; +__declspec(align(8)) struct A8 { }; #else # error No supported align as directive. #endif -// Wrap the forced aligned types in structs to hack around compiler bugs. -struct SA1 { A1 a; }; -struct SA2 { A2 a; }; -struct SA4 { A4 a; }; -struct SA8 { A8 a; }; - struct S1 {}; struct S2 { char a; }; struct S3 { int x; }; @@ -72,6 +66,17 @@ struct V6 : S1 { virtual ~V6(); }; struct V7 : virtual V2, virtual V6 { virtual ~V7(); }; struct V8 : V5, virtual V6, V7 { double zz; virtual ~V8(); }; +double S6::f() { return 0.0; } +float D2::g() { return 0.0f; } +V1::~V1() {} +V2::~V2() {} +V3::~V3() {} +V4::~V4() {} +V5::~V5() {} +V6::~V6() {} +V7::~V7() {} +V8::~V8() {} + // Ensure alignment is a compile-time constant. char LLVM_ATTRIBUTE_UNUSED test_arr1 [AlignOf<char>::Alignment > 0] @@ -90,11 +95,7 @@ char LLVM_ATTRIBUTE_UNUSED test_arr2 [AlignOf<A1>::Alignment > 0] [AlignOf<A2>::Alignment > 0] [AlignOf<A4>::Alignment > 0] - [AlignOf<A8>::Alignment > 0] - [AlignOf<SA1>::Alignment > 0] - [AlignOf<SA2>::Alignment > 0] - [AlignOf<SA4>::Alignment > 0] - [AlignOf<SA8>::Alignment > 0]; + [AlignOf<A8>::Alignment > 0]; char LLVM_ATTRIBUTE_UNUSED test_arr3 [AlignOf<S1>::Alignment > 0] [AlignOf<S2>::Alignment > 0] @@ -123,20 +124,10 @@ char LLVM_ATTRIBUTE_UNUSED test_arr5 [AlignOf<V8>::Alignment > 0]; TEST(AlignOfTest, BasicAlignmentInvariants) { - // For a very strange reason, many compilers do not support this. Both Clang - // and GCC fail to align these properly. - EXPECT_EQ(1u, alignOf<A1>()); -#if 0 - EXPECT_EQ(2u, alignOf<A2>()); - EXPECT_EQ(4u, alignOf<A4>()); - EXPECT_EQ(8u, alignOf<A8>()); -#endif - - // But once wrapped in structs, the alignment is correctly managed. - EXPECT_LE(1u, alignOf<SA1>()); - EXPECT_LE(2u, alignOf<SA2>()); - EXPECT_LE(4u, alignOf<SA4>()); - EXPECT_LE(8u, alignOf<SA8>()); + EXPECT_LE(1u, alignOf<A1>()); + EXPECT_LE(2u, alignOf<A2>()); + EXPECT_LE(4u, alignOf<A4>()); + EXPECT_LE(8u, alignOf<A8>()); EXPECT_EQ(1u, alignOf<char>()); EXPECT_LE(alignOf<char>(), alignOf<short>()); @@ -174,42 +165,38 @@ TEST(AlignOfTest, BasicAlignmentInvariants) { } TEST(AlignOfTest, BasicAlignedArray) { - // Note: this code exclusively uses the struct-wrapped arbitrarily aligned - // types because of the bugs mentioned above where GCC and Clang both - // disregard the arbitrary alignment specifier until the type is used to - // declare a member of a struct. - EXPECT_LE(1u, alignOf<AlignedCharArrayUnion<SA1> >()); - EXPECT_LE(2u, alignOf<AlignedCharArrayUnion<SA2> >()); - EXPECT_LE(4u, alignOf<AlignedCharArrayUnion<SA4> >()); - EXPECT_LE(8u, alignOf<AlignedCharArrayUnion<SA8> >()); + EXPECT_LE(1u, alignOf<AlignedCharArrayUnion<A1> >()); + EXPECT_LE(2u, alignOf<AlignedCharArrayUnion<A2> >()); + EXPECT_LE(4u, alignOf<AlignedCharArrayUnion<A4> >()); + EXPECT_LE(8u, alignOf<AlignedCharArrayUnion<A8> >()); - EXPECT_LE(1u, sizeof(AlignedCharArrayUnion<SA1>)); - EXPECT_LE(2u, sizeof(AlignedCharArrayUnion<SA2>)); - EXPECT_LE(4u, sizeof(AlignedCharArrayUnion<SA4>)); - EXPECT_LE(8u, sizeof(AlignedCharArrayUnion<SA8>)); + EXPECT_LE(1u, sizeof(AlignedCharArrayUnion<A1>)); + EXPECT_LE(2u, sizeof(AlignedCharArrayUnion<A2>)); + EXPECT_LE(4u, sizeof(AlignedCharArrayUnion<A4>)); + EXPECT_LE(8u, sizeof(AlignedCharArrayUnion<A8>)); - EXPECT_EQ(1u, (alignOf<AlignedCharArrayUnion<SA1> >())); - EXPECT_EQ(2u, (alignOf<AlignedCharArrayUnion<SA1, SA2> >())); - EXPECT_EQ(4u, (alignOf<AlignedCharArrayUnion<SA1, SA2, SA4> >())); - EXPECT_EQ(8u, (alignOf<AlignedCharArrayUnion<SA1, SA2, SA4, SA8> >())); + EXPECT_EQ(1u, (alignOf<AlignedCharArrayUnion<A1> >())); + EXPECT_EQ(2u, (alignOf<AlignedCharArrayUnion<A1, A2> >())); + EXPECT_EQ(4u, (alignOf<AlignedCharArrayUnion<A1, A2, A4> >())); + EXPECT_EQ(8u, (alignOf<AlignedCharArrayUnion<A1, A2, A4, A8> >())); - EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion<SA1>)); - EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion<SA1, SA2>)); - EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion<SA1, SA2, SA4>)); - EXPECT_EQ(8u, sizeof(AlignedCharArrayUnion<SA1, SA2, SA4, SA8>)); + EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion<A1>)); + EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion<A1, A2>)); + EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion<A1, A2, A4>)); + EXPECT_EQ(8u, sizeof(AlignedCharArrayUnion<A1, A2, A4, A8>)); - EXPECT_EQ(1u, (alignOf<AlignedCharArrayUnion<SA1[1]> >())); - EXPECT_EQ(2u, (alignOf<AlignedCharArrayUnion<SA1[2], SA2[1]> >())); - EXPECT_EQ(4u, (alignOf<AlignedCharArrayUnion<SA1[42], SA2[55], - SA4[13]> >())); - EXPECT_EQ(8u, (alignOf<AlignedCharArrayUnion<SA1[2], SA2[1], - SA4, SA8> >())); + EXPECT_EQ(1u, (alignOf<AlignedCharArrayUnion<A1[1]> >())); + EXPECT_EQ(2u, (alignOf<AlignedCharArrayUnion<A1[2], A2[1]> >())); + EXPECT_EQ(4u, (alignOf<AlignedCharArrayUnion<A1[42], A2[55], + A4[13]> >())); + EXPECT_EQ(8u, (alignOf<AlignedCharArrayUnion<A1[2], A2[1], + A4, A8> >())); - EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion<SA1[1]>)); - EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion<SA1[2], SA2[1]>)); - EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion<SA1[3], SA2[2], SA4>)); - EXPECT_EQ(16u, sizeof(AlignedCharArrayUnion<SA1, SA2[3], - SA4[3], SA8>)); + EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion<A1[1]>)); + EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion<A1[2], A2[1]>)); + EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion<A1[3], A2[2], A4>)); + EXPECT_EQ(16u, sizeof(AlignedCharArrayUnion<A1, A2[3], + A4[3], A8>)); // For other tests we simply assert that the alignment of the union mathes // that of the fundamental type and hope that we have any weird type diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 3b9bf84..09a0ea5 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -17,11 +17,14 @@ add_llvm_unittest(SupportTests LeakDetectorTest.cpp ManagedStatic.cpp MathExtrasTest.cpp + MemoryBufferTest.cpp + MemoryTest.cpp Path.cpp - raw_ostream_test.cpp RegexTest.cpp SwapByteOrderTest.cpp TimeValue.cpp ValueHandleTest.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 ca0b40b..ad564aa 100644 --- a/unittests/Support/Casting.cpp +++ b/unittests/Support/Casting.cpp @@ -95,8 +95,9 @@ TEST(CastingTest, cast) { EXPECT_NE(&F5, null_foo); const foo *F6 = cast<foo>(B4); EXPECT_NE(F6, null_foo); - foo *F7 = cast<foo>(fub()); - EXPECT_EQ(F7, null_foo); + // Can't pass null pointer to cast<>. + // foo *F7 = cast<foo>(fub()); + // EXPECT_EQ(F7, null_foo); foo *F8 = B1.baz(); EXPECT_NE(F8, null_foo); } @@ -121,7 +122,8 @@ TEST(CastingTest, dyn_cast) { EXPECT_NE(F2, null_foo); const foo *F3 = dyn_cast<foo>(B4); EXPECT_NE(F3, null_foo); - // foo *F4 = dyn_cast<foo>(fub()); // not permittible + // Can't pass null pointer to dyn_cast<>. + // foo *F4 = dyn_cast<foo>(fub()); // EXPECT_EQ(F4, null_foo); foo *F5 = B1.daz(); EXPECT_NE(F5, null_foo); @@ -151,3 +153,54 @@ const bar *B2 = &B; } // anonymous namespace bar *llvm::fub() { return 0; } + +namespace { +namespace inferred_upcasting { +// This test case verifies correct behavior of inferred upcasts when the +// types are statically known to be OK to upcast. This is the case when, +// for example, Derived inherits from Base, and we do `isa<Base>(Derived)`. + +// Note: This test will actually fail to compile without inferred +// upcasting. + +class Base { +public: + // No classof. We are testing that the upcast is inferred. + Base() {} +}; + +class Derived : public Base { +public: + Derived() {} +}; + +// Even with no explicit classof() in Base, we should still be able to cast +// Derived to its base class. +TEST(CastingTest, UpcastIsInferred) { + Derived D; + EXPECT_TRUE(isa<Base>(D)); + Base *BP = dyn_cast<Base>(&D); + EXPECT_TRUE(BP != NULL); +} + + +// This test verifies that the inferred upcast takes precedence over an +// explicitly written one. This is important because it verifies that the +// dynamic check gets optimized away. +class UseInferredUpcast { +public: + int Dummy; + static bool classof(const UseInferredUpcast *) { + return false; + } +}; + +TEST(CastingTest, InferredUpcastTakesPrecedence) { + UseInferredUpcast UIU; + // Since the explicit classof() returns false, this will fail if the + // explicit one is used. + EXPECT_TRUE(isa<UseInferredUpcast>(&UIU)); +} + +} // end namespace inferred_upcasting +} // end anonymous namespace diff --git a/unittests/Support/DataExtractorTest.cpp b/unittests/Support/DataExtractorTest.cpp index 9813e46..ec8bd3d 100644 --- a/unittests/Support/DataExtractorTest.cpp +++ b/unittests/Support/DataExtractorTest.cpp @@ -16,6 +16,7 @@ namespace { const char numberData[] = "\x80\x90\xFF\xFF\x80\x00\x00\x00"; const char stringData[] = "hellohello\0hello"; const char leb128data[] = "\xA6\x49"; +const char bigleb128data[] = "\xAA\xA9\xFF\xAA\xFF\xAA\xFF\x4A"; TEST(DataExtractorTest, OffsetOverflow) { DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8); @@ -106,6 +107,14 @@ TEST(DataExtractorTest, LEB128) { offset = 0; EXPECT_EQ(-7002LL, DE.getSLEB128(&offset)); EXPECT_EQ(2U, offset); + + DataExtractor BDE(StringRef(bigleb128data, sizeof(bigleb128data)-1), false,8); + offset = 0; + EXPECT_EQ(42218325750568106ULL, BDE.getULEB128(&offset)); + EXPECT_EQ(8U, offset); + offset = 0; + EXPECT_EQ(-29839268287359830LL, BDE.getSLEB128(&offset)); + EXPECT_EQ(8U, offset); } } diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp new file mode 100644 index 0000000..6c78cd8 --- /dev/null +++ b/unittests/Support/MemoryBufferTest.cpp @@ -0,0 +1,99 @@ +//===- llvm/unittest/Support/MemoryBufferTest.cpp - MemoryBuffer tests ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements unit tests for the MemoryBuffer support class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/ADT/OwningPtr.h" + +#include "gtest/gtest.h" + +using namespace llvm; + +class MemoryBufferTest : public testing::Test { +protected: + MemoryBufferTest() + : data("this is some data") + { } + + virtual void SetUp() { } + + typedef OwningPtr<MemoryBuffer> OwningBuffer; + + std::string data; +}; + +namespace { + +TEST_F(MemoryBufferTest, get) { + // Default name and null-terminator flag + OwningBuffer MB1(MemoryBuffer::getMemBuffer(data)); + EXPECT_TRUE(0 != MB1.get()); + + // RequiresNullTerminator = false + OwningBuffer MB2(MemoryBuffer::getMemBuffer(data, "one", false)); + EXPECT_TRUE(0 != MB2.get()); + + // RequiresNullTerminator = true + OwningBuffer MB3(MemoryBuffer::getMemBuffer(data, "two", true)); + EXPECT_TRUE(0 != MB3.get()); + + // verify all 3 buffers point to the same address + EXPECT_EQ(MB1->getBufferStart(), MB2->getBufferStart()); + EXPECT_EQ(MB2->getBufferStart(), MB3->getBufferStart()); + + // verify the original data is unmodified after deleting the buffers + MB1.reset(); + MB2.reset(); + MB3.reset(); + EXPECT_EQ("this is some data", data); +} + +TEST_F(MemoryBufferTest, copy) { + // copy with no name + OwningBuffer MBC1(MemoryBuffer::getMemBufferCopy(data)); + EXPECT_TRUE(0 != MBC1.get()); + + // copy with a name + OwningBuffer MBC2(MemoryBuffer::getMemBufferCopy(data, "copy")); + EXPECT_TRUE(0 != MBC2.get()); + + // verify the two copies do not point to the same place + EXPECT_NE(MBC1->getBufferStart(), MBC2->getBufferStart()); +} + +TEST_F(MemoryBufferTest, make_new) { + // 0-sized buffer + OwningBuffer Zero(MemoryBuffer::getNewUninitMemBuffer(0)); + EXPECT_TRUE(0 != Zero.get()); + + // uninitialized buffer with no name + OwningBuffer One(MemoryBuffer::getNewUninitMemBuffer(321)); + EXPECT_TRUE(0 != One.get()); + + // uninitialized buffer with name + OwningBuffer Two(MemoryBuffer::getNewUninitMemBuffer(123, "bla")); + EXPECT_TRUE(0 != Two.get()); + + // 0-initialized buffer with no name + OwningBuffer Three(MemoryBuffer::getNewMemBuffer(321, data)); + EXPECT_TRUE(0 != Three.get()); + for (size_t i = 0; i < 321; ++i) + EXPECT_EQ(0, Three->getBufferStart()[0]); + + // 0-initialized buffer with name + OwningBuffer Four(MemoryBuffer::getNewMemBuffer(123, "zeros")); + EXPECT_TRUE(0 != Four.get()); + for (size_t i = 0; i < 123; ++i) + EXPECT_EQ(0, Four->getBufferStart()[0]); +} + +} diff --git a/unittests/Support/MemoryTest.cpp b/unittests/Support/MemoryTest.cpp new file mode 100644 index 0000000..21cb27e --- /dev/null +++ b/unittests/Support/MemoryTest.cpp @@ -0,0 +1,356 @@ +//===- 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
diff --git a/unittests/Support/formatted_raw_ostream_test.cpp b/unittests/Support/formatted_raw_ostream_test.cpp new file mode 100644 index 0000000..4725ced --- /dev/null +++ b/unittests/Support/formatted_raw_ostream_test.cpp @@ -0,0 +1,33 @@ +//===- llvm/unittest/Support/formatted_raw_ostream_test.cpp ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; + +namespace { + +TEST(formatted_raw_ostreamTest, Test_Tell) { + // Check offset when underlying stream has buffer contents. + SmallString<128> A; + raw_svector_ostream B(A); + formatted_raw_ostream C(B); + char tmp[100] = ""; + + for (unsigned i = 0; i != 3; ++i) { + C.write(tmp, 100); + + EXPECT_EQ(100*(i+1), (unsigned) C.tell()); + } +} + +} |