1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <gtest/gtest.h> 18 19#include <errno.h> 20#include <unistd.h> 21#include <fcntl.h> 22#include <sys/mman.h> 23 24#include "pmemalloc.h" 25 26class DepsStub : public PmemUserspaceAllocator::Deps, public PmemKernelAllocator::Deps { 27 28 public: 29 30 virtual size_t getPmemTotalSize(int fd, size_t* size) { 31 return 0; 32 } 33 34 virtual int connectPmem(int fd, int master_fd) { 35 return 0; 36 } 37 38 virtual int mapPmem(int fd, int offset, size_t size) { 39 return 0; 40 } 41 42 virtual int unmapPmem(int fd, int offset, size_t size) { 43 return 0; 44 } 45 46 virtual int getErrno() { 47 return 0; 48 } 49 50 virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, 51 off_t offset) { 52 return 0; 53 } 54 55 virtual int munmap(void* start, size_t length) { 56 return 0; 57 } 58 59 virtual int open(const char* pathname, int flags, int mode) { 60 return 0; 61 } 62 63 virtual int close(int fd) { 64 return 0; 65 } 66}; 67 68/******************************************************************************/ 69 70class AllocatorStub : public PmemUserspaceAllocator::Deps::Allocator { 71 virtual ssize_t setSize(size_t size) { 72 return 0; 73 } 74 75 virtual size_t size() const { 76 return 0; 77 } 78 79 virtual ssize_t allocate(size_t size, uint32_t flags = 0) { 80 return 0; 81 } 82 83 virtual ssize_t deallocate(size_t offset) { 84 return 0; 85 } 86}; 87 88/******************************************************************************/ 89 90static const char* fakePmemDev = "/foo/bar"; 91 92/******************************************************************************/ 93 94struct Deps_InitPmemAreaLockedWithSuccessfulCompletion : public DepsStub { 95 96 virtual int open(const char* pathname, int flags, int mode) { 97 EXPECT_EQ(fakePmemDev, pathname); 98 EXPECT_EQ(O_RDWR, flags); 99 EXPECT_EQ(0, mode); 100 return 1234; 101 } 102 103 virtual size_t getPmemTotalSize(int fd, size_t* size) { 104 EXPECT_EQ(1234, fd); 105 *size = 16 << 20; 106 return 0; 107 } 108 109 virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, 110 off_t offset) { 111 EXPECT_EQ(1234, fd); 112 return (void*)0x87654321; 113 } 114 115}; 116 117struct Allocator_InitPmemAreaLockedWithSuccessfulCompletion : public AllocatorStub { 118 119 virtual ssize_t setSize(size_t size) { 120 EXPECT_EQ(size_t(16 << 20), size); 121 return 0; 122 } 123}; 124 125TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithSuccessfulCompletion) { 126 Deps_InitPmemAreaLockedWithSuccessfulCompletion depsMock; 127 Allocator_InitPmemAreaLockedWithSuccessfulCompletion allocMock; 128 PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); 129 130 int result = pma.init_pmem_area_locked(); 131 ASSERT_EQ(0, result); 132} 133 134/******************************************************************************/ 135 136struct Deps_InitPmemAreaLockedWithEnomemOnMmap : public DepsStub { 137 138 virtual int open(const char* pathname, int flags, int mode) { 139 EXPECT_EQ(fakePmemDev, pathname); 140 EXPECT_EQ(O_RDWR, flags); 141 EXPECT_EQ(0, mode); 142 return 1234; 143 } 144 145 virtual size_t getPmemTotalSize(int fd, size_t* size) { 146 EXPECT_EQ(1234, fd); 147 *size = 16 << 20; 148 return 0; 149 } 150 151 virtual int getErrno() { 152 return ENOMEM; 153 } 154 155 virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, 156 off_t offset) { 157 return (void*)MAP_FAILED; 158 } 159 160}; 161 162struct Allocator_InitPmemAreaLockedWithEnomemOnMmap : public AllocatorStub { 163 164 virtual ssize_t setSize(size_t size) { 165 EXPECT_EQ(size_t(16 << 20), size); 166 return 0; 167 } 168}; 169 170TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEnomemOnMmap) { 171 Deps_InitPmemAreaLockedWithEnomemOnMmap depsMock; 172 Allocator_InitPmemAreaLockedWithEnomemOnMmap allocMock; 173 PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); 174 175 int result = pma.init_pmem_area_locked(); 176 ASSERT_EQ(-ENOMEM, result); 177} 178 179/******************************************************************************/ 180 181struct Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize : public DepsStub { 182 183 virtual int open(const char* pathname, int flags, int mode) { 184 EXPECT_EQ(fakePmemDev, pathname); 185 EXPECT_EQ(O_RDWR, flags); 186 EXPECT_EQ(0, mode); 187 return 1234; 188 } 189 190 virtual size_t getPmemTotalSize(int fd, size_t* size) { 191 EXPECT_EQ(1234, fd); 192 return -EACCES; 193 } 194}; 195 196TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEaccesOnGetPmemTotalSize) { 197 Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize depsMock; 198 AllocatorStub allocStub; 199 PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); 200 201 int result = pma.init_pmem_area_locked(); 202 ASSERT_EQ(-EACCES, result); 203} 204 205/******************************************************************************/ 206 207struct Deps_InitPmemAreaLockedWithEaccesOnOpen : public DepsStub { 208 209 virtual int getErrno() { 210 return EACCES; 211 } 212 213 virtual int open(const char* pathname, int flags, int mode) { 214 EXPECT_EQ(fakePmemDev, pathname); 215 EXPECT_EQ(O_RDWR, flags); 216 EXPECT_EQ(0, mode); 217 return -1; 218 } 219}; 220 221TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithEaccesOnOpenMaster) { 222 Deps_InitPmemAreaLockedWithEaccesOnOpen depsMock; 223 AllocatorStub allocStub; 224 PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); 225 226 int result = pma.init_pmem_area_locked(); 227 ASSERT_EQ(-EACCES, result); 228} 229 230/******************************************************************************/ 231 232typedef Deps_InitPmemAreaLockedWithSuccessfulCompletion Deps_InitPmemAreaWithSuccessfulInitialCompletion; 233 234TEST(test_pmem_userspace_allocator, testInitPmemAreaWithSuccessfulInitialCompletion) { 235 Deps_InitPmemAreaWithSuccessfulInitialCompletion depsMock; 236 AllocatorStub allocStub; 237 PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); 238 239 int result = pma.init_pmem_area(); 240 ASSERT_EQ(0, result); 241} 242 243/******************************************************************************/ 244 245typedef Deps_InitPmemAreaLockedWithEaccesOnOpen Deps_InitPmemAreaWithEaccesOnInitLocked; 246 247TEST(test_pmem_userspace_allocator, testInitPmemAreaWithEaccesOnInitLocked) { 248 Deps_InitPmemAreaWithEaccesOnInitLocked depsMock; 249 AllocatorStub allocStub; 250 PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); 251 252 int result = pma.init_pmem_area(); 253 ASSERT_EQ(-EACCES, result); 254} 255 256/******************************************************************************/ 257 258TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterSuccessfulInitialCompletion) { 259 DepsStub depsStub; 260 AllocatorStub allocStub; 261 PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev); 262 263 pma.set_master_values(1234, 0); // Indicate that the pma has been successfully init'd 264 265 int result = pma.init_pmem_area(); 266 ASSERT_EQ(0, result); 267 //XXX JMG: Add this back in maybe? ASSERT_EQ(1234, pmi.master); // Make sure the master fd wasn't changed 268} 269 270/******************************************************************************/ 271 272TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterFailedInit) { 273 DepsStub depsStub; 274 AllocatorStub allocStub; 275 PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev); 276 277 pma.set_master_values(-EACCES, 0); // Indicate that the pma has failed init 278 279 int result = pma.init_pmem_area(); 280 ASSERT_EQ(-EACCES, result); 281} 282 283/******************************************************************************/ 284 285struct Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags : public DepsStub { 286 287 virtual int open(const char* pathname, int flags, int mode) { 288 EXPECT_EQ(fakePmemDev, pathname); 289 EXPECT_EQ(O_RDWR, flags & O_RDWR); 290 EXPECT_EQ(0, mode); 291 return 5678; 292 } 293 294 virtual int connectPmem(int fd, int master_fd) { 295 EXPECT_EQ(5678, fd); 296 EXPECT_EQ(1234, master_fd); 297 return 0; 298 } 299 300 virtual int mapPmem(int fd, int offset, size_t size) { 301 EXPECT_EQ(5678, fd); 302 EXPECT_EQ(0x300, offset); 303 EXPECT_EQ(size_t(0x100), size); 304 return 0; 305 } 306}; 307 308 309struct Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags : public AllocatorStub { 310 311 virtual ssize_t allocate(size_t size, uint32_t flags = 0) { 312 EXPECT_EQ(size_t(0x100), size); 313 EXPECT_EQ(uint32_t(0x0), flags); 314 return 0x300; 315 } 316}; 317 318TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) { 319 Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags depsMock; 320 Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags allocMock; 321 PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); 322 323 uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd 324 pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd 325 326 void* base = 0; 327 int offset = -9182, fd = -9182; 328 int size = 0x100; 329 int flags = 0; 330 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 331 ASSERT_EQ(0, result); 332 ASSERT_EQ(0x300, offset); 333 ASSERT_EQ(5678, fd); 334 for (int i = 0x300; i < 0x400; ++i) { 335 ASSERT_EQ(uint8_t(0), buf[i]); 336 } 337} 338 339/******************************************************************************/ 340 341typedef Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags; 342 343typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags; 344 345TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) { 346 Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags depsMock; 347 Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags allocMock; 348 PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); 349 350 uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd 351 pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd 352 353 void* base = 0; 354 int offset = -9182, fd = -9182; 355 int size = 0x100; 356 int flags = ~0; 357 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 358 ASSERT_EQ(0, result); 359 ASSERT_EQ(0x300, offset); 360 ASSERT_EQ(5678, fd); 361 for (int i = 0x300; i < 0x400; ++i) { 362 ASSERT_EQ(0, buf[i]); 363 } 364} 365 366/******************************************************************************/ 367 368struct Deps_InitPmemAreaLockedWithEnodevOnOpen : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { 369 370 virtual int getErrno() { 371 return ENODEV; 372 } 373 374 virtual int open(const char* pathname, int flags, int mode) { 375 EXPECT_EQ(fakePmemDev, pathname); 376 EXPECT_EQ(O_RDWR, flags & O_RDWR); 377 EXPECT_EQ(0, mode); 378 return -1; 379 } 380}; 381 382typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnodevOnOpen; 383 384TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnodevOnOpen) { 385 Deps_InitPmemAreaLockedWithEnodevOnOpen depsMock; 386 Allocator_AllocPmemBufferWithEnodevOnOpen allocMock; 387 PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); 388 389 uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd 390 pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd 391 392 void* base = 0; 393 int offset = -9182, fd = -9182; 394 int size = 0x100; 395 int flags = ~0; 396 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 397 ASSERT_EQ(-ENODEV, result); 398} 399 400/******************************************************************************/ 401 402struct Deps_InitPmemAreaLockedWithEnomemOnConnectPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { 403 404 virtual int getErrno() { 405 return ENOMEM; 406 } 407 408 virtual int connectPmem(int fd, int master_fd) { 409 EXPECT_EQ(5678, fd); 410 EXPECT_EQ(1234, master_fd); 411 return -1; 412 } 413}; 414 415typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnConnectPmem; 416 417TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnomemOnConnectPmem) { 418 Deps_InitPmemAreaLockedWithEnomemOnConnectPmem depsMock; 419 Allocator_AllocPmemBufferWithEnomemOnConnectPmem allocMock; 420 PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); 421 422 uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd 423 pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd 424 425 void* base = 0; 426 int offset = -9182, fd = -9182; 427 int size = 0x100; 428 int flags = ~0; 429 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 430 ASSERT_EQ(-ENOMEM, result); 431} 432 433/******************************************************************************/ 434 435struct Deps_InitPmemAreaLockedWithEnomemOnMapPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { 436 437 virtual int getErrno() { 438 return ENOMEM; 439 } 440 441 virtual int mapPmem(int fd, int offset, size_t size) { 442 EXPECT_EQ(5678, fd); 443 EXPECT_EQ(0x300, offset); 444 EXPECT_EQ(size_t(0x100), size); 445 return -1; 446 } 447}; 448 449typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnMapPmem; 450 451TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithEnomemOnMapPmem) { 452 Deps_InitPmemAreaLockedWithEnomemOnMapPmem depsMock; 453 Allocator_AllocPmemBufferWithEnomemOnMapPmem allocMock; 454 PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); 455 456 uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd 457 pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd 458 459 void* base = 0; 460 int offset = -9182, fd = -9182; 461 int size = 0x100; 462 int flags = ~0; 463 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 464 ASSERT_EQ(-ENOMEM, result); 465} 466 467/******************************************************************************/ 468 469struct Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags : public DepsStub { 470 471 void* mmapResult; 472 473 Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags(void* mmapResult) : 474 mmapResult(mmapResult) {} 475 476 virtual int open(const char* pathname, int flags, int mode) { 477 EXPECT_EQ(fakePmemDev, pathname); 478 EXPECT_EQ(O_RDWR, flags & O_RDWR); 479 EXPECT_EQ(0, mode); 480 return 5678; 481 } 482 483 virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, 484 off_t offset) { 485 EXPECT_EQ(5678, fd); 486 return mmapResult; 487 } 488}; 489 490TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) { 491 uint8_t buf[0x100]; // Create a buffer to get memzero'd 492 Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags depsMock(buf); 493 PmemKernelAllocator pma(depsMock, fakePmemDev); 494 495 void* base = 0; 496 int offset = -9182, fd = -9182; 497 int size = 0x100; 498 int flags = 0; 499 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 500 ASSERT_EQ(0, result); 501 ASSERT_EQ(buf, base); 502 ASSERT_EQ(0, offset); 503 ASSERT_EQ(5678, fd); 504 for (int i = 0; i < 0x100; ++i) { 505 ASSERT_EQ(0, buf[i]); 506 } 507} 508 509/******************************************************************************/ 510 511typedef Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags; 512 513TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) { 514 uint8_t buf[0x100]; // Create a buffer to get memzero'd 515 Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags depsMock(buf); 516 PmemKernelAllocator pma(depsMock, fakePmemDev); 517 518 void* base = 0; 519 int offset = -9182, fd = -9182; 520 int size = 0x100; 521 int flags = ~0; 522 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 523 ASSERT_EQ(0, result); 524 ASSERT_EQ(buf, base); 525 ASSERT_EQ(0, offset); 526 ASSERT_EQ(5678, fd); 527 for (int i = 0; i < 0x100; ++i) { 528 ASSERT_EQ(0, buf[i]); 529 } 530} 531 532/******************************************************************************/ 533 534struct Deps_KernelAllocPmemBufferWithEpermOnOpen : public DepsStub { 535 536 virtual int getErrno() { 537 return EPERM; 538 } 539 540 virtual int open(const char* pathname, int flags, int mode) { 541 EXPECT_EQ(fakePmemDev, pathname); 542 EXPECT_EQ(O_RDWR, flags & O_RDWR); 543 EXPECT_EQ(0, mode); 544 return -1; 545 } 546}; 547 548 549TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEpermOnOpen) { 550 Deps_KernelAllocPmemBufferWithEpermOnOpen depsMock; 551 PmemKernelAllocator pma(depsMock, fakePmemDev); 552 553 void* base = 0; 554 int offset = -9182, fd = -9182; 555 int size = 0x100; 556 int flags = ~0; 557 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 558 ASSERT_EQ(-EPERM, result); 559 ASSERT_EQ(0, base); 560 ASSERT_EQ(0, offset); 561 ASSERT_EQ(-1, fd); 562} 563 564/******************************************************************************/ 565 566struct Deps_KernelAllocPmemBufferWithEnomemOnMmap : DepsStub { 567 568 virtual int open(const char* pathname, int flags, int mode) { 569 EXPECT_EQ(fakePmemDev, pathname); 570 EXPECT_EQ(O_RDWR, flags & O_RDWR); 571 EXPECT_EQ(0, mode); 572 return 5678; 573 } 574 575 virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, 576 off_t offset) { 577 return (void*)MAP_FAILED; 578 } 579 580 virtual int getErrno() { 581 return ENOMEM; 582 } 583}; 584 585 586TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEnomemOnMmap) { 587 Deps_KernelAllocPmemBufferWithEnomemOnMmap depsMock; 588 PmemKernelAllocator pma(depsMock, fakePmemDev); 589 590 void* base = 0; 591 int offset = -9182, fd = -9182; 592 int size = 0x100; 593 int flags = ~0; 594 int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); 595 ASSERT_EQ(-ENOMEM, result); 596 ASSERT_EQ(0, base); 597 ASSERT_EQ(0, offset); 598 ASSERT_EQ(-1, fd); 599} 600 601/******************************************************************************/ 602