| // Copyright 2020 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 "host-common/address_space_shared_slots_host_memory_allocator.h" |
| #include <gtest/gtest.h> |
| |
| namespace android { |
| namespace emulation { |
| namespace { |
| typedef AddressSpaceSharedSlotsHostMemoryAllocatorContext ASSSHMAC; |
| typedef ASSSHMAC::MemBlock MemBlock; |
| typedef MemBlock::FreeSubblocks_t FreeSubblocks_t; |
| |
| int add_memory_mapping(uint64_t gpa, void *ptr, uint64_t size) { |
| return 1; |
| } |
| |
| int remove_memory_mapping(uint64_t gpa, void *ptr, uint64_t size) { return 1; } |
| |
| struct address_space_device_control_ops create_address_space_device_control_ops() { |
| struct address_space_device_control_ops ops = {}; |
| |
| ops.add_memory_mapping = &add_memory_mapping; |
| ops.remove_memory_mapping = &remove_memory_mapping; |
| |
| return ops; |
| } |
| |
| uint64_t getPhysAddrStartLocked(void) { |
| return 2020; |
| } |
| |
| int allocSharedHostRegionLocked(uint64_t page_aligned_size, uint64_t* offset) { |
| *offset = page_aligned_size * 10; |
| return 0; |
| } |
| |
| int freeSharedHostRegionLocked(uint64_t offset) { |
| return 0; |
| } |
| |
| AddressSpaceHwFuncs create_AddressSpaceHwFuncs() { |
| AddressSpaceHwFuncs hw = {}; |
| |
| hw.allocSharedHostRegionLocked = &allocSharedHostRegionLocked; |
| hw.freeSharedHostRegionLocked = &freeSharedHostRegionLocked; |
| hw.getPhysAddrStartLocked = &getPhysAddrStartLocked; |
| |
| return hw; |
| } |
| } |
| |
| TEST(MemBlock_findFreeSubblock, Simple) { |
| FreeSubblocks_t fsb; |
| EXPECT_TRUE(MemBlock::findFreeSubblock(&fsb, 11) == fsb.end()); |
| |
| fsb[100] = 10; |
| EXPECT_TRUE(MemBlock::findFreeSubblock(&fsb, 11) == fsb.end()); |
| |
| FreeSubblocks_t::const_iterator i; |
| |
| i = MemBlock::findFreeSubblock(&fsb, 7); |
| ASSERT_TRUE(i != fsb.end()); |
| EXPECT_EQ(i->first, 100); |
| EXPECT_EQ(i->second, 10); |
| |
| fsb[200] = 6; |
| i = MemBlock::findFreeSubblock(&fsb, 7); |
| ASSERT_TRUE(i != fsb.end()); |
| EXPECT_EQ(i->first, 100); |
| EXPECT_EQ(i->second, 10); |
| |
| fsb[300] = 8; |
| i = MemBlock::findFreeSubblock(&fsb, 7); |
| ASSERT_TRUE(i != fsb.end()); |
| EXPECT_EQ(i->first, 300); |
| EXPECT_EQ(i->second, 8); |
| } |
| |
| TEST(MemBlock_tryMergeSubblocks, NoMerge) { |
| FreeSubblocks_t fsb; |
| |
| auto i = fsb.insert({10, 5}).first; |
| auto j = fsb.insert({20, 5}).first; |
| |
| auto r = MemBlock::tryMergeSubblocks(&fsb, i, i, j); |
| |
| EXPECT_EQ(fsb.size(), 2); |
| EXPECT_EQ(fsb[10], 5); |
| EXPECT_EQ(fsb[20], 5); |
| EXPECT_TRUE(r == i); |
| } |
| |
| TEST(MemBlock_tryMergeSubblocks, Merge) { |
| FreeSubblocks_t fsb; |
| |
| auto i = fsb.insert({10, 10}).first; |
| auto j = fsb.insert({20, 5}).first; |
| |
| auto r = MemBlock::tryMergeSubblocks(&fsb, i, i, j); |
| |
| EXPECT_EQ(fsb.size(), 1); |
| EXPECT_EQ(fsb[10], 15); |
| ASSERT_TRUE(r != fsb.end()); |
| EXPECT_EQ(r->first, 10); |
| EXPECT_EQ(r->second, 15); |
| } |
| |
| TEST(MemBlock, allocate) { |
| const struct address_space_device_control_ops ops = |
| create_address_space_device_control_ops(); |
| |
| const AddressSpaceHwFuncs hw = create_AddressSpaceHwFuncs(); |
| |
| MemBlock block(&ops, &hw, 100); |
| EXPECT_TRUE(block.isAllFree()); |
| EXPECT_EQ(block.physBase, 2020 + 100 * 10); |
| |
| EXPECT_EQ(block.allocate(110), 0); // too large |
| |
| uint32_t off; |
| |
| off = block.allocate(50); |
| EXPECT_GE(off, 2020 + 100 * 10); |
| |
| off = block.allocate(47); |
| EXPECT_GE(off, 2020 + 100 * 10); |
| |
| off = block.allocate(2); |
| EXPECT_GE(off, 2020 + 100 * 10); |
| |
| off = block.allocate(2); |
| EXPECT_EQ(off, 0); |
| |
| off = block.allocate(1); |
| EXPECT_GE(off, 2020 + 100 * 10); |
| |
| off = block.allocate(1); |
| EXPECT_EQ(off, 0); |
| } |
| |
| TEST(MemBlock, unallocate) { |
| const struct address_space_device_control_ops ops = |
| create_address_space_device_control_ops(); |
| |
| const AddressSpaceHwFuncs hw = create_AddressSpaceHwFuncs(); |
| |
| MemBlock block(&ops, &hw, 100); |
| EXPECT_TRUE(block.isAllFree()); |
| EXPECT_EQ(block.physBase, 2020 + 100 * 10); |
| |
| uint32_t off60 = block.allocate(60); |
| EXPECT_GE(off60, 2020 + 100 * 10); |
| |
| uint32_t off20 = block.allocate(20); |
| EXPECT_GE(off20, 2020 + 100 * 10); |
| |
| uint32_t off30 = block.allocate(30); |
| EXPECT_EQ(off30, 0); |
| |
| block.unallocate(off20, 20); |
| |
| off30 = block.allocate(30); |
| EXPECT_GE(off30, 2020 + 100 * 10); |
| |
| block.unallocate(off60, 60); |
| block.unallocate(off30, 30); |
| |
| EXPECT_TRUE(block.isAllFree()); |
| } |
| |
| } // namespace emulation |
| } // namespace android |