| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <gtest/gtest.h> |
| |
| #include <errno.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <sys/mman.h> |
| |
| #include "pmemalloc.h" |
| |
| class DepsStub : public PmemUserspaceAllocator::Deps, public PmemKernelAllocator::Deps { |
| |
| public: |
| |
| virtual size_t getPmemTotalSize(int fd, size_t* size) { |
| return 0; |
| } |
| |
| virtual int connectPmem(int fd, int master_fd) { |
| return 0; |
| } |
| |
| virtual int mapPmem(int fd, int offset, size_t size) { |
| return 0; |
| } |
| |
| virtual int unmapPmem(int fd, int offset, size_t size) { |
| return 0; |
| } |
| |
| virtual int getErrno() { |
| return 0; |
| } |
| |
| virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, |
| off_t offset) { |
| return 0; |
| } |
| |
| virtual int munmap(void* start, size_t length) { |
| return 0; |
| } |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| return 0; |
| } |
| |
| virtual int close(int fd) { |
| return 0; |
| } |
| }; |
| |
| /******************************************************************************/ |
| |
| class AllocatorStub : public PmemUserspaceAllocator::Deps::Allocator { |
| virtual ssize_t setSize(size_t size) { |
| return 0; |
| } |
| |
| virtual size_t size() const { |
| return 0; |
| } |
| |
| virtual ssize_t allocate(size_t size, uint32_t flags = 0) { |
| return 0; |
| } |
| |
| virtual ssize_t deallocate(size_t offset) { |
| return 0; |
| } |
| }; |
| |
| /******************************************************************************/ |
| |
| static const char* fakePmemDev = "/foo/bar"; |
| |
| /******************************************************************************/ |
| |
| struct Deps_InitPmemAreaLockedWithSuccessfulCompletion : public DepsStub { |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags); |
| EXPECT_EQ(0, mode); |
| return 1234; |
| } |
| |
| virtual size_t getPmemTotalSize(int fd, size_t* size) { |
| EXPECT_EQ(1234, fd); |
| *size = 16 << 20; |
| return 0; |
| } |
| |
| virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, |
| off_t offset) { |
| EXPECT_EQ(1234, fd); |
| return (void*)0x87654321; |
| } |
| |
| }; |
| |
| struct Allocator_InitPmemAreaLockedWithSuccessfulCompletion : public AllocatorStub { |
| |
| virtual ssize_t setSize(size_t size) { |
| EXPECT_EQ(size_t(16 << 20), size); |
| return 0; |
| } |
| }; |
| |
| TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithSuccessfulCompletion) { |
| Deps_InitPmemAreaLockedWithSuccessfulCompletion depsMock; |
| Allocator_InitPmemAreaLockedWithSuccessfulCompletion allocMock; |
| PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); |
| |
| int result = pma.init_pmem_area_locked(); |
| ASSERT_EQ(0, result); |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_InitPmemAreaLockedWithEnomemOnMmap : public DepsStub { |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags); |
| EXPECT_EQ(0, mode); |
| return 1234; |
| } |
| |
| virtual size_t getPmemTotalSize(int fd, size_t* size) { |
| EXPECT_EQ(1234, fd); |
| *size = 16 << 20; |
| return 0; |
| } |
| |
| virtual int getErrno() { |
| return ENOMEM; |
| } |
| |
| virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, |
| off_t offset) { |
| return (void*)MAP_FAILED; |
| } |
| |
| }; |
| |
| struct Allocator_InitPmemAreaLockedWithEnomemOnMmap : public AllocatorStub { |
| |
| virtual ssize_t setSize(size_t size) { |
| EXPECT_EQ(size_t(16 << 20), size); |
| return 0; |
| } |
| }; |
| |
| TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEnomemOnMmap) { |
| Deps_InitPmemAreaLockedWithEnomemOnMmap depsMock; |
| Allocator_InitPmemAreaLockedWithEnomemOnMmap allocMock; |
| PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); |
| |
| int result = pma.init_pmem_area_locked(); |
| ASSERT_EQ(-ENOMEM, result); |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize : public DepsStub { |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags); |
| EXPECT_EQ(0, mode); |
| return 1234; |
| } |
| |
| virtual size_t getPmemTotalSize(int fd, size_t* size) { |
| EXPECT_EQ(1234, fd); |
| return -EACCES; |
| } |
| }; |
| |
| TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEaccesOnGetPmemTotalSize) { |
| Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize depsMock; |
| AllocatorStub allocStub; |
| PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); |
| |
| int result = pma.init_pmem_area_locked(); |
| ASSERT_EQ(-EACCES, result); |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_InitPmemAreaLockedWithEaccesOnOpen : public DepsStub { |
| |
| virtual int getErrno() { |
| return EACCES; |
| } |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags); |
| EXPECT_EQ(0, mode); |
| return -1; |
| } |
| }; |
| |
| TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithEaccesOnOpenMaster) { |
| Deps_InitPmemAreaLockedWithEaccesOnOpen depsMock; |
| AllocatorStub allocStub; |
| PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); |
| |
| int result = pma.init_pmem_area_locked(); |
| ASSERT_EQ(-EACCES, result); |
| } |
| |
| /******************************************************************************/ |
| |
| typedef Deps_InitPmemAreaLockedWithSuccessfulCompletion Deps_InitPmemAreaWithSuccessfulInitialCompletion; |
| |
| TEST(test_pmem_userspace_allocator, testInitPmemAreaWithSuccessfulInitialCompletion) { |
| Deps_InitPmemAreaWithSuccessfulInitialCompletion depsMock; |
| AllocatorStub allocStub; |
| PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); |
| |
| int result = pma.init_pmem_area(); |
| ASSERT_EQ(0, result); |
| } |
| |
| /******************************************************************************/ |
| |
| typedef Deps_InitPmemAreaLockedWithEaccesOnOpen Deps_InitPmemAreaWithEaccesOnInitLocked; |
| |
| TEST(test_pmem_userspace_allocator, testInitPmemAreaWithEaccesOnInitLocked) { |
| Deps_InitPmemAreaWithEaccesOnInitLocked depsMock; |
| AllocatorStub allocStub; |
| PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); |
| |
| int result = pma.init_pmem_area(); |
| ASSERT_EQ(-EACCES, result); |
| } |
| |
| /******************************************************************************/ |
| |
| TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterSuccessfulInitialCompletion) { |
| DepsStub depsStub; |
| AllocatorStub allocStub; |
| PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev); |
| |
| pma.set_master_values(1234, 0); // Indicate that the pma has been successfully init'd |
| |
| int result = pma.init_pmem_area(); |
| ASSERT_EQ(0, result); |
| //XXX JMG: Add this back in maybe? ASSERT_EQ(1234, pmi.master); // Make sure the master fd wasn't changed |
| } |
| |
| /******************************************************************************/ |
| |
| TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterFailedInit) { |
| DepsStub depsStub; |
| AllocatorStub allocStub; |
| PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev); |
| |
| pma.set_master_values(-EACCES, 0); // Indicate that the pma has failed init |
| |
| int result = pma.init_pmem_area(); |
| ASSERT_EQ(-EACCES, result); |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags : public DepsStub { |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags & O_RDWR); |
| EXPECT_EQ(0, mode); |
| return 5678; |
| } |
| |
| virtual int connectPmem(int fd, int master_fd) { |
| EXPECT_EQ(5678, fd); |
| EXPECT_EQ(1234, master_fd); |
| return 0; |
| } |
| |
| virtual int mapPmem(int fd, int offset, size_t size) { |
| EXPECT_EQ(5678, fd); |
| EXPECT_EQ(0x300, offset); |
| EXPECT_EQ(size_t(0x100), size); |
| return 0; |
| } |
| }; |
| |
| |
| struct Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags : public AllocatorStub { |
| |
| virtual ssize_t allocate(size_t size, uint32_t flags = 0) { |
| EXPECT_EQ(size_t(0x100), size); |
| EXPECT_EQ(uint32_t(0x0), flags); |
| return 0x300; |
| } |
| }; |
| |
| TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) { |
| Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags depsMock; |
| Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags allocMock; |
| PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); |
| |
| uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd |
| pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = 0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(0, result); |
| ASSERT_EQ(0x300, offset); |
| ASSERT_EQ(5678, fd); |
| for (int i = 0x300; i < 0x400; ++i) { |
| ASSERT_EQ(uint8_t(0), buf[i]); |
| } |
| } |
| |
| /******************************************************************************/ |
| |
| typedef Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags; |
| |
| typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags; |
| |
| TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) { |
| Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags depsMock; |
| Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags allocMock; |
| PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); |
| |
| uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd |
| pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = ~0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(0, result); |
| ASSERT_EQ(0x300, offset); |
| ASSERT_EQ(5678, fd); |
| for (int i = 0x300; i < 0x400; ++i) { |
| ASSERT_EQ(0, buf[i]); |
| } |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_InitPmemAreaLockedWithEnodevOnOpen : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { |
| |
| virtual int getErrno() { |
| return ENODEV; |
| } |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags & O_RDWR); |
| EXPECT_EQ(0, mode); |
| return -1; |
| } |
| }; |
| |
| typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnodevOnOpen; |
| |
| TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnodevOnOpen) { |
| Deps_InitPmemAreaLockedWithEnodevOnOpen depsMock; |
| Allocator_AllocPmemBufferWithEnodevOnOpen allocMock; |
| PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); |
| |
| uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd |
| pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = ~0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(-ENODEV, result); |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_InitPmemAreaLockedWithEnomemOnConnectPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { |
| |
| virtual int getErrno() { |
| return ENOMEM; |
| } |
| |
| virtual int connectPmem(int fd, int master_fd) { |
| EXPECT_EQ(5678, fd); |
| EXPECT_EQ(1234, master_fd); |
| return -1; |
| } |
| }; |
| |
| typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnConnectPmem; |
| |
| TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnomemOnConnectPmem) { |
| Deps_InitPmemAreaLockedWithEnomemOnConnectPmem depsMock; |
| Allocator_AllocPmemBufferWithEnomemOnConnectPmem allocMock; |
| PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); |
| |
| uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd |
| pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = ~0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(-ENOMEM, result); |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_InitPmemAreaLockedWithEnomemOnMapPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { |
| |
| virtual int getErrno() { |
| return ENOMEM; |
| } |
| |
| virtual int mapPmem(int fd, int offset, size_t size) { |
| EXPECT_EQ(5678, fd); |
| EXPECT_EQ(0x300, offset); |
| EXPECT_EQ(size_t(0x100), size); |
| return -1; |
| } |
| }; |
| |
| typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnMapPmem; |
| |
| TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithEnomemOnMapPmem) { |
| Deps_InitPmemAreaLockedWithEnomemOnMapPmem depsMock; |
| Allocator_AllocPmemBufferWithEnomemOnMapPmem allocMock; |
| PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); |
| |
| uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd |
| pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = ~0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(-ENOMEM, result); |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags : public DepsStub { |
| |
| void* mmapResult; |
| |
| Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags(void* mmapResult) : |
| mmapResult(mmapResult) {} |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags & O_RDWR); |
| EXPECT_EQ(0, mode); |
| return 5678; |
| } |
| |
| virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, |
| off_t offset) { |
| EXPECT_EQ(5678, fd); |
| return mmapResult; |
| } |
| }; |
| |
| TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) { |
| uint8_t buf[0x100]; // Create a buffer to get memzero'd |
| Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags depsMock(buf); |
| PmemKernelAllocator pma(depsMock, fakePmemDev); |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = 0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(0, result); |
| ASSERT_EQ(buf, base); |
| ASSERT_EQ(0, offset); |
| ASSERT_EQ(5678, fd); |
| for (int i = 0; i < 0x100; ++i) { |
| ASSERT_EQ(0, buf[i]); |
| } |
| } |
| |
| /******************************************************************************/ |
| |
| typedef Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags; |
| |
| TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) { |
| uint8_t buf[0x100]; // Create a buffer to get memzero'd |
| Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags depsMock(buf); |
| PmemKernelAllocator pma(depsMock, fakePmemDev); |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = ~0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(0, result); |
| ASSERT_EQ(buf, base); |
| ASSERT_EQ(0, offset); |
| ASSERT_EQ(5678, fd); |
| for (int i = 0; i < 0x100; ++i) { |
| ASSERT_EQ(0, buf[i]); |
| } |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_KernelAllocPmemBufferWithEpermOnOpen : public DepsStub { |
| |
| virtual int getErrno() { |
| return EPERM; |
| } |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags & O_RDWR); |
| EXPECT_EQ(0, mode); |
| return -1; |
| } |
| }; |
| |
| |
| TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEpermOnOpen) { |
| Deps_KernelAllocPmemBufferWithEpermOnOpen depsMock; |
| PmemKernelAllocator pma(depsMock, fakePmemDev); |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = ~0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(-EPERM, result); |
| ASSERT_EQ(0, base); |
| ASSERT_EQ(0, offset); |
| ASSERT_EQ(-1, fd); |
| } |
| |
| /******************************************************************************/ |
| |
| struct Deps_KernelAllocPmemBufferWithEnomemOnMmap : DepsStub { |
| |
| virtual int open(const char* pathname, int flags, int mode) { |
| EXPECT_EQ(fakePmemDev, pathname); |
| EXPECT_EQ(O_RDWR, flags & O_RDWR); |
| EXPECT_EQ(0, mode); |
| return 5678; |
| } |
| |
| virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, |
| off_t offset) { |
| return (void*)MAP_FAILED; |
| } |
| |
| virtual int getErrno() { |
| return ENOMEM; |
| } |
| }; |
| |
| |
| TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEnomemOnMmap) { |
| Deps_KernelAllocPmemBufferWithEnomemOnMmap depsMock; |
| PmemKernelAllocator pma(depsMock, fakePmemDev); |
| |
| void* base = 0; |
| int offset = -9182, fd = -9182; |
| int size = 0x100; |
| int flags = ~0; |
| int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); |
| ASSERT_EQ(-ENOMEM, result); |
| ASSERT_EQ(0, base); |
| ASSERT_EQ(0, offset); |
| ASSERT_EQ(-1, fd); |
| } |
| |
| /******************************************************************************/ |