11f661007SAndrew Kaylor //===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//
21f661007SAndrew Kaylor //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61f661007SAndrew Kaylor //
71f661007SAndrew Kaylor //===----------------------------------------------------------------------===//
81f661007SAndrew Kaylor 
91f661007SAndrew Kaylor #include "llvm/Support/Memory.h"
101f661007SAndrew Kaylor #include "llvm/Support/Process.h"
111f661007SAndrew Kaylor #include "gtest/gtest.h"
121b25ba07SMichal Gorny #include <cassert>
131f661007SAndrew Kaylor #include <cstdlib>
141f661007SAndrew Kaylor 
151b25ba07SMichal Gorny #if defined(__NetBSD__)
161b25ba07SMichal Gorny // clang-format off
171b25ba07SMichal Gorny #include <sys/param.h>
181b25ba07SMichal Gorny #include <sys/types.h>
191b25ba07SMichal Gorny #include <sys/sysctl.h>
201b25ba07SMichal Gorny #include <err.h>
211b25ba07SMichal Gorny #include <unistd.h>
221b25ba07SMichal Gorny // clang-format on
231b25ba07SMichal Gorny #endif
241b25ba07SMichal Gorny 
251f661007SAndrew Kaylor using namespace llvm;
261f661007SAndrew Kaylor using namespace sys;
271f661007SAndrew Kaylor 
281f661007SAndrew Kaylor namespace {
291f661007SAndrew Kaylor 
IsMPROTECT()301b25ba07SMichal Gorny bool IsMPROTECT() {
311b25ba07SMichal Gorny #if defined(__NetBSD__)
321b25ba07SMichal Gorny   int mib[3];
331b25ba07SMichal Gorny   int paxflags;
341b25ba07SMichal Gorny   size_t len = sizeof(paxflags);
351b25ba07SMichal Gorny 
361b25ba07SMichal Gorny   mib[0] = CTL_PROC;
371b25ba07SMichal Gorny   mib[1] = getpid();
381b25ba07SMichal Gorny   mib[2] = PROC_PID_PAXFLAGS;
391b25ba07SMichal Gorny 
401b25ba07SMichal Gorny   if (sysctl(mib, 3, &paxflags, &len, NULL, 0) != 0)
411b25ba07SMichal Gorny     err(EXIT_FAILURE, "sysctl");
421b25ba07SMichal Gorny 
431b25ba07SMichal Gorny   return !!(paxflags & CTL_PROC_PAXFLAGS_MPROTECT);
44eaa09823SNico Weber #elif defined(__APPLE__) && defined(__aarch64__)
45eaa09823SNico Weber   return true;
461b25ba07SMichal Gorny #else
471b25ba07SMichal Gorny   return false;
481b25ba07SMichal Gorny #endif
491b25ba07SMichal Gorny }
501b25ba07SMichal Gorny 
511f661007SAndrew Kaylor class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
521f661007SAndrew Kaylor public:
MappedMemoryTest()531f661007SAndrew Kaylor   MappedMemoryTest() {
541f661007SAndrew Kaylor     Flags = GetParam();
55e4b4ab6dSLang Hames     PageSize = sys::Process::getPageSizeEstimate();
561f661007SAndrew Kaylor   }
571f661007SAndrew Kaylor 
581f661007SAndrew Kaylor protected:
591f661007SAndrew Kaylor   // Adds RW flags to permit testing of the resulting memory
getTestableEquivalent(unsigned RequestedFlags)601f661007SAndrew Kaylor   unsigned getTestableEquivalent(unsigned RequestedFlags) {
611f661007SAndrew Kaylor     switch (RequestedFlags) {
621f661007SAndrew Kaylor     case Memory::MF_READ:
631f661007SAndrew Kaylor     case Memory::MF_WRITE:
641f661007SAndrew Kaylor     case Memory::MF_READ|Memory::MF_WRITE:
651f661007SAndrew Kaylor       return Memory::MF_READ|Memory::MF_WRITE;
661f661007SAndrew Kaylor     case Memory::MF_READ|Memory::MF_EXEC:
671f661007SAndrew Kaylor     case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
681f661007SAndrew Kaylor     case Memory::MF_EXEC:
691f661007SAndrew Kaylor       return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
701f661007SAndrew Kaylor     }
711f661007SAndrew Kaylor     // Default in case values are added to the enum, as required by some compilers
721f661007SAndrew Kaylor     return Memory::MF_READ|Memory::MF_WRITE;
731f661007SAndrew Kaylor   }
741f661007SAndrew Kaylor 
751f661007SAndrew Kaylor   // Returns true if the memory blocks overlap
doesOverlap(MemoryBlock M1,MemoryBlock M2)761f661007SAndrew Kaylor   bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {
771f661007SAndrew Kaylor     if (M1.base() == M2.base())
781f661007SAndrew Kaylor       return true;
791f661007SAndrew Kaylor 
801f661007SAndrew Kaylor     if (M1.base() > M2.base())
8193d2bddaSLang Hames       return (unsigned char *)M2.base() + M2.allocatedSize() > M1.base();
821f661007SAndrew Kaylor 
8393d2bddaSLang Hames     return (unsigned char *)M1.base() + M1.allocatedSize() > M2.base();
841f661007SAndrew Kaylor   }
851f661007SAndrew Kaylor 
861f661007SAndrew Kaylor   unsigned Flags;
871f661007SAndrew Kaylor   size_t   PageSize;
881f661007SAndrew Kaylor };
891f661007SAndrew Kaylor 
901b25ba07SMichal Gorny // MPROTECT prevents W+X mmaps
911b25ba07SMichal Gorny #define CHECK_UNSUPPORTED() \
921b25ba07SMichal Gorny   do { \
931b25ba07SMichal Gorny     if ((Flags & Memory::MF_WRITE) && (Flags & Memory::MF_EXEC) && \
941b25ba07SMichal Gorny         IsMPROTECT()) \
951b25ba07SMichal Gorny       return; \
961b25ba07SMichal Gorny   } while (0)
971b25ba07SMichal Gorny 
TEST_P(MappedMemoryTest,AllocAndRelease)981f661007SAndrew Kaylor TEST_P(MappedMemoryTest, AllocAndRelease) {
991b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
100c049c657SRafael Espindola   std::error_code EC;
10166f09ad0SCraig Topper   MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
102c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
1031f661007SAndrew Kaylor 
10466f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
10593d2bddaSLang Hames   EXPECT_LE(sizeof(int), M1.allocatedSize());
1061f661007SAndrew Kaylor 
1071f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
1081f661007SAndrew Kaylor }
1091f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,AllocAndReleaseHuge)110b05ba935SAlexandre Ganea TEST_P(MappedMemoryTest, AllocAndReleaseHuge) {
111b05ba935SAlexandre Ganea   CHECK_UNSUPPORTED();
112b05ba935SAlexandre Ganea   std::error_code EC;
113b05ba935SAlexandre Ganea   MemoryBlock M1 = Memory::allocateMappedMemory(
114b05ba935SAlexandre Ganea       sizeof(int), nullptr, Flags | Memory::MF_HUGE_HINT, EC);
115b05ba935SAlexandre Ganea   EXPECT_EQ(std::error_code(), EC);
116b05ba935SAlexandre Ganea 
117b05ba935SAlexandre Ganea   // Test large/huge memory pages. In the worst case, 4kb pages should be
118b05ba935SAlexandre Ganea   // returned, if large pages aren't available.
119b05ba935SAlexandre Ganea 
120b05ba935SAlexandre Ganea   EXPECT_NE((void *)nullptr, M1.base());
12193d2bddaSLang Hames   EXPECT_LE(sizeof(int), M1.allocatedSize());
122b05ba935SAlexandre Ganea 
123b05ba935SAlexandre Ganea   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
124b05ba935SAlexandre Ganea }
125b05ba935SAlexandre Ganea 
TEST_P(MappedMemoryTest,MultipleAllocAndRelease)1261f661007SAndrew Kaylor TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
1271b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
128c049c657SRafael Espindola   std::error_code EC;
12966f09ad0SCraig Topper   MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
130c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
13166f09ad0SCraig Topper   MemoryBlock M2 = Memory::allocateMappedMemory(64, nullptr, Flags, EC);
132c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
13366f09ad0SCraig Topper   MemoryBlock M3 = Memory::allocateMappedMemory(32, nullptr, Flags, EC);
134c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
1351f661007SAndrew Kaylor 
13666f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
13793d2bddaSLang Hames   EXPECT_LE(16U, M1.allocatedSize());
13866f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M2.base());
13993d2bddaSLang Hames   EXPECT_LE(64U, M2.allocatedSize());
14066f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M3.base());
14193d2bddaSLang Hames   EXPECT_LE(32U, M3.allocatedSize());
1421f661007SAndrew Kaylor 
1431f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M2));
1441f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M2, M3));
1451f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M3));
1461f661007SAndrew Kaylor 
1471f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
1481f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
14966f09ad0SCraig Topper   MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
150c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
15166f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M4.base());
15293d2bddaSLang Hames   EXPECT_LE(16U, M4.allocatedSize());
1531f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M4));
1541f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
1551f661007SAndrew Kaylor }
1561f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,BasicWrite)1571f661007SAndrew Kaylor TEST_P(MappedMemoryTest, BasicWrite) {
1584b11df0dSAkira Hatanaka   // This test applies only to readable and writeable combinations
1594b11df0dSAkira Hatanaka   if (Flags &&
1604b11df0dSAkira Hatanaka       !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
1611f661007SAndrew Kaylor     return;
1621b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
1631f661007SAndrew Kaylor 
164c049c657SRafael Espindola   std::error_code EC;
16566f09ad0SCraig Topper   MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
166c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
1671f661007SAndrew Kaylor 
16866f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
16993d2bddaSLang Hames   EXPECT_LE(sizeof(int), M1.allocatedSize());
1701f661007SAndrew Kaylor 
1711f661007SAndrew Kaylor   int *a = (int*)M1.base();
1721f661007SAndrew Kaylor   *a = 1;
1731f661007SAndrew Kaylor   EXPECT_EQ(1, *a);
1741f661007SAndrew Kaylor 
1751f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
1761f661007SAndrew Kaylor }
1771f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,MultipleWrite)1781f661007SAndrew Kaylor TEST_P(MappedMemoryTest, MultipleWrite) {
1794b11df0dSAkira Hatanaka   // This test applies only to readable and writeable combinations
1804b11df0dSAkira Hatanaka   if (Flags &&
1814b11df0dSAkira Hatanaka       !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
1821f661007SAndrew Kaylor     return;
1831b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
1841b25ba07SMichal Gorny 
185c049c657SRafael Espindola   std::error_code EC;
18666f09ad0SCraig Topper   MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,
18766f09ad0SCraig Topper                                                 EC);
188c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
18966f09ad0SCraig Topper   MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
19066f09ad0SCraig Topper                                                 EC);
191c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
19266f09ad0SCraig Topper   MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
19366f09ad0SCraig Topper                                                 EC);
194c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
1951f661007SAndrew Kaylor 
1961f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M2));
1971f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M2, M3));
1981f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M3));
1991f661007SAndrew Kaylor 
20066f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
20193d2bddaSLang Hames   EXPECT_LE(1U * sizeof(int), M1.allocatedSize());
20266f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M2.base());
20393d2bddaSLang Hames   EXPECT_LE(8U * sizeof(int), M2.allocatedSize());
20466f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M3.base());
20593d2bddaSLang Hames   EXPECT_LE(4U * sizeof(int), M3.allocatedSize());
2061f661007SAndrew Kaylor 
2071f661007SAndrew Kaylor   int *x = (int*)M1.base();
2081f661007SAndrew Kaylor   *x = 1;
2091f661007SAndrew Kaylor 
2101f661007SAndrew Kaylor   int *y = (int*)M2.base();
2111f661007SAndrew Kaylor   for (int i = 0; i < 8; i++) {
2121f661007SAndrew Kaylor     y[i] = i;
2131f661007SAndrew Kaylor   }
2141f661007SAndrew Kaylor 
2151f661007SAndrew Kaylor   int *z = (int*)M3.base();
2161f661007SAndrew Kaylor   *z = 42;
2171f661007SAndrew Kaylor 
2181f661007SAndrew Kaylor   EXPECT_EQ(1, *x);
2191f661007SAndrew Kaylor   EXPECT_EQ(7, y[7]);
2201f661007SAndrew Kaylor   EXPECT_EQ(42, *z);
2211f661007SAndrew Kaylor 
2221f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
2231f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
2241f661007SAndrew Kaylor 
22566f09ad0SCraig Topper   MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), nullptr,
22666f09ad0SCraig Topper                                                 Flags, EC);
227c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
22866f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M4.base());
22993d2bddaSLang Hames   EXPECT_LE(64U * sizeof(int), M4.allocatedSize());
2301f661007SAndrew Kaylor   x = (int*)M4.base();
2311f661007SAndrew Kaylor   *x = 4;
2321f661007SAndrew Kaylor   EXPECT_EQ(4, *x);
2331f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M4));
2341f661007SAndrew Kaylor 
2351f661007SAndrew Kaylor   // Verify that M2 remains unaffected by other activity
2361f661007SAndrew Kaylor   for (int i = 0; i < 8; i++) {
2371f661007SAndrew Kaylor     EXPECT_EQ(i, y[i]);
2381f661007SAndrew Kaylor   }
2391f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
2401f661007SAndrew Kaylor }
2411f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,EnabledWrite)2421f661007SAndrew Kaylor TEST_P(MappedMemoryTest, EnabledWrite) {
2431b25ba07SMichal Gorny   // MPROTECT prevents W+X, and since this test always adds W we need
2441b25ba07SMichal Gorny   // to block any variant with X.
2451b25ba07SMichal Gorny   if ((Flags & Memory::MF_EXEC) && IsMPROTECT())
2461b25ba07SMichal Gorny     return;
2471b25ba07SMichal Gorny 
248c049c657SRafael Espindola   std::error_code EC;
24966f09ad0SCraig Topper   MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags,
25066f09ad0SCraig Topper                                                 EC);
251c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
25266f09ad0SCraig Topper   MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
25366f09ad0SCraig Topper                                                 EC);
254c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
25566f09ad0SCraig Topper   MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
25666f09ad0SCraig Topper                                                 EC);
257c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
2581f661007SAndrew Kaylor 
25966f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
26093d2bddaSLang Hames   EXPECT_LE(2U * sizeof(int), M1.allocatedSize());
26166f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M2.base());
26293d2bddaSLang Hames   EXPECT_LE(8U * sizeof(int), M2.allocatedSize());
26366f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M3.base());
26493d2bddaSLang Hames   EXPECT_LE(4U * sizeof(int), M3.allocatedSize());
2651f661007SAndrew Kaylor 
2661f661007SAndrew Kaylor   EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
2671f661007SAndrew Kaylor   EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
2681f661007SAndrew Kaylor   EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
2691f661007SAndrew Kaylor 
2701f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M2));
2711f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M2, M3));
2721f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M3));
2731f661007SAndrew Kaylor 
2741f661007SAndrew Kaylor   int *x = (int*)M1.base();
2751f661007SAndrew Kaylor   *x = 1;
2761f661007SAndrew Kaylor   int *y = (int*)M2.base();
2771f661007SAndrew Kaylor   for (unsigned int i = 0; i < 8; i++) {
2781f661007SAndrew Kaylor     y[i] = i;
2791f661007SAndrew Kaylor   }
2801f661007SAndrew Kaylor   int *z = (int*)M3.base();
2811f661007SAndrew Kaylor   *z = 42;
2821f661007SAndrew Kaylor 
2831f661007SAndrew Kaylor   EXPECT_EQ(1, *x);
2841f661007SAndrew Kaylor   EXPECT_EQ(7, y[7]);
2851f661007SAndrew Kaylor   EXPECT_EQ(42, *z);
2861f661007SAndrew Kaylor 
2871f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
2881f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
2891f661007SAndrew Kaylor   EXPECT_EQ(6, y[6]);
2901f661007SAndrew Kaylor 
29166f09ad0SCraig Topper   MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
292c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
29366f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M4.base());
29493d2bddaSLang Hames   EXPECT_LE(16U, M4.allocatedSize());
295c049c657SRafael Espindola   EXPECT_EQ(std::error_code(),
296c049c657SRafael Espindola             Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
2971f661007SAndrew Kaylor   x = (int*)M4.base();
2981f661007SAndrew Kaylor   *x = 4;
2991f661007SAndrew Kaylor   EXPECT_EQ(4, *x);
3001f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M4));
3011f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
3021f661007SAndrew Kaylor }
3031f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,SuccessiveNear)3041f661007SAndrew Kaylor TEST_P(MappedMemoryTest, SuccessiveNear) {
3051b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
306c049c657SRafael Espindola   std::error_code EC;
30766f09ad0SCraig Topper   MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
308c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3091f661007SAndrew Kaylor   MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
310c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3111f661007SAndrew Kaylor   MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
312c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3131f661007SAndrew Kaylor 
31466f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
31593d2bddaSLang Hames   EXPECT_LE(16U, M1.allocatedSize());
31666f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M2.base());
31793d2bddaSLang Hames   EXPECT_LE(64U, M2.allocatedSize());
31866f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M3.base());
31993d2bddaSLang Hames   EXPECT_LE(32U, M3.allocatedSize());
3201f661007SAndrew Kaylor 
3211f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M2));
3221f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M2, M3));
3231f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M3));
3241f661007SAndrew Kaylor 
3251f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
3261f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
3271f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
3281f661007SAndrew Kaylor }
3291f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,DuplicateNear)3301f661007SAndrew Kaylor TEST_P(MappedMemoryTest, DuplicateNear) {
3311b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
332c049c657SRafael Espindola   std::error_code EC;
3331f661007SAndrew Kaylor   MemoryBlock Near((void*)(3*PageSize), 16);
3341f661007SAndrew Kaylor   MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
335c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3361f661007SAndrew Kaylor   MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
337c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3381f661007SAndrew Kaylor   MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
339c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3401f661007SAndrew Kaylor 
34166f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
34293d2bddaSLang Hames   EXPECT_LE(16U, M1.allocatedSize());
34366f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M2.base());
34493d2bddaSLang Hames   EXPECT_LE(64U, M2.allocatedSize());
34566f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M3.base());
34693d2bddaSLang Hames   EXPECT_LE(32U, M3.allocatedSize());
3471f661007SAndrew Kaylor 
3481f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
3491f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
3501f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
3511f661007SAndrew Kaylor }
3521f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,ZeroNear)3531f661007SAndrew Kaylor TEST_P(MappedMemoryTest, ZeroNear) {
3541b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
355c049c657SRafael Espindola   std::error_code EC;
35666f09ad0SCraig Topper   MemoryBlock Near(nullptr, 0);
3571f661007SAndrew Kaylor   MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
358c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3591f661007SAndrew Kaylor   MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
360c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3611f661007SAndrew Kaylor   MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
362c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3631f661007SAndrew Kaylor 
36466f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
36593d2bddaSLang Hames   EXPECT_LE(16U, M1.allocatedSize());
36666f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M2.base());
36793d2bddaSLang Hames   EXPECT_LE(64U, M2.allocatedSize());
36866f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M3.base());
36993d2bddaSLang Hames   EXPECT_LE(32U, M3.allocatedSize());
3701f661007SAndrew Kaylor 
3711f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M2));
3721f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M2, M3));
3731f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M3));
3741f661007SAndrew Kaylor 
3751f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
3761f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
3771f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
3781f661007SAndrew Kaylor }
3791f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,ZeroSizeNear)3801f661007SAndrew Kaylor TEST_P(MappedMemoryTest, ZeroSizeNear) {
3811b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
382c049c657SRafael Espindola   std::error_code EC;
3831f661007SAndrew Kaylor   MemoryBlock Near((void*)(4*PageSize), 0);
3841f661007SAndrew Kaylor   MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
385c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3861f661007SAndrew Kaylor   MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
387c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3881f661007SAndrew Kaylor   MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
389c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
3901f661007SAndrew Kaylor 
39166f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
39293d2bddaSLang Hames   EXPECT_LE(16U, M1.allocatedSize());
39366f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M2.base());
39493d2bddaSLang Hames   EXPECT_LE(64U, M2.allocatedSize());
39566f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M3.base());
39693d2bddaSLang Hames   EXPECT_LE(32U, M3.allocatedSize());
3971f661007SAndrew Kaylor 
3981f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M2));
3991f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M2, M3));
4001f661007SAndrew Kaylor   EXPECT_FALSE(doesOverlap(M1, M3));
4011f661007SAndrew Kaylor 
4021f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
4031f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
4041f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M2));
4051f661007SAndrew Kaylor }
4061f661007SAndrew Kaylor 
TEST_P(MappedMemoryTest,UnalignedNear)4071f661007SAndrew Kaylor TEST_P(MappedMemoryTest, UnalignedNear) {
4081b25ba07SMichal Gorny   CHECK_UNSUPPORTED();
409c049c657SRafael Espindola   std::error_code EC;
4101f661007SAndrew Kaylor   MemoryBlock Near((void*)(2*PageSize+5), 0);
4111f661007SAndrew Kaylor   MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
412c049c657SRafael Espindola   EXPECT_EQ(std::error_code(), EC);
4131f661007SAndrew Kaylor 
41466f09ad0SCraig Topper   EXPECT_NE((void*)nullptr, M1.base());
41593d2bddaSLang Hames   EXPECT_LE(sizeof(int), M1.allocatedSize());
4161f661007SAndrew Kaylor 
4171f661007SAndrew Kaylor   EXPECT_FALSE(Memory::releaseMappedMemory(M1));
4181f661007SAndrew Kaylor }
4191f661007SAndrew Kaylor 
4201f661007SAndrew Kaylor // Note that Memory::MF_WRITE is not supported exclusively across
4211f661007SAndrew Kaylor // operating systems and architectures and can imply MF_READ|MF_WRITE
4221f661007SAndrew Kaylor unsigned MemoryFlags[] = {
4231f661007SAndrew Kaylor                            Memory::MF_READ,
4241f661007SAndrew Kaylor                            Memory::MF_WRITE,
4251f661007SAndrew Kaylor                            Memory::MF_READ|Memory::MF_WRITE,
4261f661007SAndrew Kaylor                            Memory::MF_EXEC,
4271f661007SAndrew Kaylor                            Memory::MF_READ|Memory::MF_EXEC,
4281f661007SAndrew Kaylor                            Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
4291f661007SAndrew Kaylor                          };
4301f661007SAndrew Kaylor 
431*d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P(AllocationTests, MappedMemoryTest,
432*d4d80a29SBenjamin Kramer                          ::testing::ValuesIn(MemoryFlags));
4331f661007SAndrew Kaylor 
4341f661007SAndrew Kaylor }  // anonymous namespace
435