-//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "llvm/Support/Memory.h"\r
-#include "llvm/Support/Process.h"\r
-\r
-#include "gtest/gtest.h"\r
-#include <cstdlib>\r
-\r
-using namespace llvm;\r
-using namespace sys;\r
-\r
-namespace {\r
-\r
-class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {\r
-public:\r
- MappedMemoryTest() {\r
- Flags = GetParam();\r
- PageSize = sys::Process::GetPageSize();\r
- }\r
-\r
-protected:\r
- // Adds RW flags to permit testing of the resulting memory\r
- unsigned getTestableEquivalent(unsigned RequestedFlags) {\r
- switch (RequestedFlags) {\r
- case Memory::MF_READ:\r
- case Memory::MF_WRITE:\r
- case Memory::MF_READ|Memory::MF_WRITE:\r
- return Memory::MF_READ|Memory::MF_WRITE;\r
- case Memory::MF_READ|Memory::MF_EXEC:\r
- case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:\r
- case Memory::MF_EXEC:\r
- return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;\r
- }\r
- // Default in case values are added to the enum, as required by some compilers\r
- return Memory::MF_READ|Memory::MF_WRITE;\r
- }\r
-\r
- // Returns true if the memory blocks overlap\r
- bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {\r
- if (M1.base() == M2.base())\r
- return true;\r
-\r
- if (M1.base() > M2.base())\r
- return (unsigned char *)M2.base() + M2.size() > M1.base();\r
-\r
- return (unsigned char *)M1.base() + M1.size() > M2.base();\r
- }\r
-\r
- unsigned Flags;\r
- size_t PageSize;\r
-};\r
-\r
-TEST_P(MappedMemoryTest, AllocAndRelease) {\r
- error_code EC;\r
- MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(sizeof(int), M1.size());\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {\r
- error_code EC;\r
- MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M2 = Memory::allocateMappedMemory(64, 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M3 = Memory::allocateMappedMemory(32, 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(16U, M1.size());\r
- EXPECT_NE((void*)0, M2.base());\r
- EXPECT_LE(64U, M2.size());\r
- EXPECT_NE((void*)0, M3.base());\r
- EXPECT_LE(32U, M3.size());\r
-\r
- EXPECT_FALSE(doesOverlap(M1, M2));\r
- EXPECT_FALSE(doesOverlap(M2, M3));\r
- EXPECT_FALSE(doesOverlap(M1, M3));\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));\r
- MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- EXPECT_NE((void*)0, M4.base());\r
- EXPECT_LE(16U, M4.size());\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M4));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, BasicWrite) {\r
- // This test applies only to writeable combinations\r
- if (Flags && !(Flags & Memory::MF_WRITE))\r
- return;\r
-\r
- error_code EC;\r
- MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(sizeof(int), M1.size());\r
-\r
- int *a = (int*)M1.base();\r
- *a = 1;\r
- EXPECT_EQ(1, *a);\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, MultipleWrite) {\r
- // This test applies only to writeable combinations\r
- if (Flags && !(Flags & Memory::MF_WRITE))\r
- return;\r
- error_code EC;\r
- MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_FALSE(doesOverlap(M1, M2));\r
- EXPECT_FALSE(doesOverlap(M2, M3));\r
- EXPECT_FALSE(doesOverlap(M1, M3));\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(1U * sizeof(int), M1.size());\r
- EXPECT_NE((void*)0, M2.base());\r
- EXPECT_LE(8U * sizeof(int), M2.size());\r
- EXPECT_NE((void*)0, M3.base());\r
- EXPECT_LE(4U * sizeof(int), M3.size());\r
-\r
- int *x = (int*)M1.base();\r
- *x = 1;\r
-\r
- int *y = (int*)M2.base();\r
- for (int i = 0; i < 8; i++) {\r
- y[i] = i;\r
- }\r
-\r
- int *z = (int*)M3.base();\r
- *z = 42;\r
-\r
- EXPECT_EQ(1, *x);\r
- EXPECT_EQ(7, y[7]);\r
- EXPECT_EQ(42, *z);\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));\r
-\r
- MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- EXPECT_NE((void*)0, M4.base());\r
- EXPECT_LE(64U * sizeof(int), M4.size());\r
- x = (int*)M4.base();\r
- *x = 4;\r
- EXPECT_EQ(4, *x);\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M4));\r
-\r
- // Verify that M2 remains unaffected by other activity\r
- for (int i = 0; i < 8; i++) {\r
- EXPECT_EQ(i, y[i]);\r
- }\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, EnabledWrite) {\r
- error_code EC;\r
- MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(2U * sizeof(int), M1.size());\r
- EXPECT_NE((void*)0, M2.base());\r
- EXPECT_LE(8U * sizeof(int), M2.size());\r
- EXPECT_NE((void*)0, M3.base());\r
- EXPECT_LE(4U * sizeof(int), M3.size());\r
-\r
- EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));\r
- EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));\r
- EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));\r
-\r
- EXPECT_FALSE(doesOverlap(M1, M2));\r
- EXPECT_FALSE(doesOverlap(M2, M3));\r
- EXPECT_FALSE(doesOverlap(M1, M3));\r
-\r
- int *x = (int*)M1.base();\r
- *x = 1;\r
- int *y = (int*)M2.base();\r
- for (unsigned int i = 0; i < 8; i++) {\r
- y[i] = i;\r
- }\r
- int *z = (int*)M3.base();\r
- *z = 42;\r
-\r
- EXPECT_EQ(1, *x);\r
- EXPECT_EQ(7, y[7]);\r
- EXPECT_EQ(42, *z);\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));\r
- EXPECT_EQ(6, y[6]);\r
-\r
- MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- EXPECT_NE((void*)0, M4.base());\r
- EXPECT_LE(16U, M4.size());\r
- EXPECT_EQ(error_code::success(), Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));\r
- x = (int*)M4.base();\r
- *x = 4;\r
- EXPECT_EQ(4, *x);\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M4));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, SuccessiveNear) {\r
- error_code EC;\r
- MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(16U, M1.size());\r
- EXPECT_NE((void*)0, M2.base());\r
- EXPECT_LE(64U, M2.size());\r
- EXPECT_NE((void*)0, M3.base());\r
- EXPECT_LE(32U, M3.size());\r
-\r
- EXPECT_FALSE(doesOverlap(M1, M2));\r
- EXPECT_FALSE(doesOverlap(M2, M3));\r
- EXPECT_FALSE(doesOverlap(M1, M3));\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, DuplicateNear) {\r
- error_code EC;\r
- MemoryBlock Near((void*)(3*PageSize), 16);\r
- MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(16U, M1.size());\r
- EXPECT_NE((void*)0, M2.base());\r
- EXPECT_LE(64U, M2.size());\r
- EXPECT_NE((void*)0, M3.base());\r
- EXPECT_LE(32U, M3.size());\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, ZeroNear) {\r
- error_code EC;\r
- MemoryBlock Near(0, 0);\r
- MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(16U, M1.size());\r
- EXPECT_NE((void*)0, M2.base());\r
- EXPECT_LE(64U, M2.size());\r
- EXPECT_NE((void*)0, M3.base());\r
- EXPECT_LE(32U, M3.size());\r
-\r
- EXPECT_FALSE(doesOverlap(M1, M2));\r
- EXPECT_FALSE(doesOverlap(M2, M3));\r
- EXPECT_FALSE(doesOverlap(M1, M3));\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, ZeroSizeNear) {\r
- error_code EC;\r
- MemoryBlock Near((void*)(4*PageSize), 0);\r
- MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
- MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(16U, M1.size());\r
- EXPECT_NE((void*)0, M2.base());\r
- EXPECT_LE(64U, M2.size());\r
- EXPECT_NE((void*)0, M3.base());\r
- EXPECT_LE(32U, M3.size());\r
-\r
- EXPECT_FALSE(doesOverlap(M1, M2));\r
- EXPECT_FALSE(doesOverlap(M2, M3));\r
- EXPECT_FALSE(doesOverlap(M1, M3));\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M3));\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M2));\r
-}\r
-\r
-TEST_P(MappedMemoryTest, UnalignedNear) {\r
- error_code EC;\r
- MemoryBlock Near((void*)(2*PageSize+5), 0);\r
- MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);\r
- EXPECT_EQ(error_code::success(), EC);\r
-\r
- EXPECT_NE((void*)0, M1.base());\r
- EXPECT_LE(sizeof(int), M1.size());\r
-\r
- EXPECT_FALSE(Memory::releaseMappedMemory(M1));\r
-}\r
-\r
-// Note that Memory::MF_WRITE is not supported exclusively across\r
-// operating systems and architectures and can imply MF_READ|MF_WRITE\r
-unsigned MemoryFlags[] = {\r
- Memory::MF_READ,\r
- Memory::MF_WRITE,\r
- Memory::MF_READ|Memory::MF_WRITE,\r
- Memory::MF_EXEC,\r
- Memory::MF_READ|Memory::MF_EXEC,\r
- Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC\r
- };\r
-\r
-INSTANTIATE_TEST_CASE_P(AllocationTests,\r
- MappedMemoryTest,\r
- ::testing::ValuesIn(MemoryFlags));\r
-\r
-} // anonymous namespace\r
+//===- 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