blob: a25bfba7a88c581f6ea41d5b4feb91b8bae5649c [file] [log] [blame]
// 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