Remove the 'N' modifier from llvm-ar.
[oota-llvm.git] / unittests / Support / MemoryTest.cpp
index 21cb27eaf0ef2b117f79244a3bd90fff14040bb8..fae67a8dd2569a495b8aef11fc348b4849ac1ef2 100644 (file)
-//===- 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::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