1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "host-common/address_space_shared_slots_host_memory_allocator.h"
16 #include <gtest/gtest.h>
17 
18 namespace android {
19 namespace emulation {
20 namespace {
21 typedef AddressSpaceSharedSlotsHostMemoryAllocatorContext ASSSHMAC;
22 typedef ASSSHMAC::MemBlock MemBlock;
23 typedef MemBlock::FreeSubblocks_t FreeSubblocks_t;
24 
add_memory_mapping(uint64_t gpa,void * ptr,uint64_t size)25 int add_memory_mapping(uint64_t gpa, void *ptr, uint64_t size) {
26     return 1;
27 }
28 
remove_memory_mapping(uint64_t gpa,void * ptr,uint64_t size)29 int remove_memory_mapping(uint64_t gpa, void *ptr, uint64_t size) { return 1; }
30 
create_address_space_device_control_ops()31 struct address_space_device_control_ops create_address_space_device_control_ops() {
32     struct address_space_device_control_ops ops = {};
33 
34     ops.add_memory_mapping = &add_memory_mapping;
35     ops.remove_memory_mapping = &remove_memory_mapping;
36 
37     return ops;
38 }
39 
getPhysAddrStartLocked(void)40 uint64_t getPhysAddrStartLocked(void) {
41     return 2020;
42 }
43 
allocSharedHostRegionLocked(uint64_t page_aligned_size,uint64_t * offset)44 int allocSharedHostRegionLocked(uint64_t page_aligned_size, uint64_t* offset) {
45     *offset = page_aligned_size * 10;
46     return 0;
47 }
48 
freeSharedHostRegionLocked(uint64_t offset)49 int freeSharedHostRegionLocked(uint64_t offset) {
50     return 0;
51 }
52 
create_AddressSpaceHwFuncs()53 AddressSpaceHwFuncs create_AddressSpaceHwFuncs() {
54     AddressSpaceHwFuncs hw = {};
55 
56     hw.allocSharedHostRegionLocked = &allocSharedHostRegionLocked;
57     hw.freeSharedHostRegionLocked = &freeSharedHostRegionLocked;
58     hw.getPhysAddrStartLocked = &getPhysAddrStartLocked;
59 
60     return hw;
61 }
62 }
63 
TEST(MemBlock_findFreeSubblock,Simple)64 TEST(MemBlock_findFreeSubblock, Simple) {
65     FreeSubblocks_t fsb;
66     EXPECT_TRUE(MemBlock::findFreeSubblock(&fsb, 11) == fsb.end());
67 
68     fsb[100] = 10;
69     EXPECT_TRUE(MemBlock::findFreeSubblock(&fsb, 11) == fsb.end());
70 
71     FreeSubblocks_t::const_iterator i;
72 
73     i = MemBlock::findFreeSubblock(&fsb, 7);
74     ASSERT_TRUE(i != fsb.end());
75     EXPECT_EQ(i->first, 100);
76     EXPECT_EQ(i->second, 10);
77 
78     fsb[200] = 6;
79     i = MemBlock::findFreeSubblock(&fsb, 7);
80     ASSERT_TRUE(i != fsb.end());
81     EXPECT_EQ(i->first, 100);
82     EXPECT_EQ(i->second, 10);
83 
84     fsb[300] = 8;
85     i = MemBlock::findFreeSubblock(&fsb, 7);
86     ASSERT_TRUE(i != fsb.end());
87     EXPECT_EQ(i->first, 300);
88     EXPECT_EQ(i->second, 8);
89 }
90 
TEST(MemBlock_tryMergeSubblocks,NoMerge)91 TEST(MemBlock_tryMergeSubblocks, NoMerge) {
92     FreeSubblocks_t fsb;
93 
94     auto i = fsb.insert({10, 5}).first;
95     auto j = fsb.insert({20, 5}).first;
96 
97     auto r = MemBlock::tryMergeSubblocks(&fsb, i, i, j);
98 
99     EXPECT_EQ(fsb.size(), 2);
100     EXPECT_EQ(fsb[10], 5);
101     EXPECT_EQ(fsb[20], 5);
102     EXPECT_TRUE(r == i);
103 }
104 
TEST(MemBlock_tryMergeSubblocks,Merge)105 TEST(MemBlock_tryMergeSubblocks, Merge) {
106     FreeSubblocks_t fsb;
107 
108     auto i = fsb.insert({10, 10}).first;
109     auto j = fsb.insert({20, 5}).first;
110 
111     auto r = MemBlock::tryMergeSubblocks(&fsb, i, i, j);
112 
113     EXPECT_EQ(fsb.size(), 1);
114     EXPECT_EQ(fsb[10], 15);
115     ASSERT_TRUE(r != fsb.end());
116     EXPECT_EQ(r->first, 10);
117     EXPECT_EQ(r->second, 15);
118 }
119 
TEST(MemBlock,allocate)120 TEST(MemBlock, allocate) {
121     const struct address_space_device_control_ops ops =
122         create_address_space_device_control_ops();
123 
124     const AddressSpaceHwFuncs hw = create_AddressSpaceHwFuncs();
125 
126     MemBlock block(&ops, &hw, 100);
127     EXPECT_TRUE(block.isAllFree());
128     EXPECT_EQ(block.physBase, 2020 + 100 * 10);
129 
130     EXPECT_EQ(block.allocate(110), 0);  // too large
131 
132     uint32_t off;
133 
134     off = block.allocate(50);
135     EXPECT_GE(off, 2020 + 100 * 10);
136 
137     off = block.allocate(47);
138     EXPECT_GE(off, 2020 + 100 * 10);
139 
140     off = block.allocate(2);
141     EXPECT_GE(off, 2020 + 100 * 10);
142 
143     off = block.allocate(2);
144     EXPECT_EQ(off, 0);
145 
146     off = block.allocate(1);
147     EXPECT_GE(off, 2020 + 100 * 10);
148 
149     off = block.allocate(1);
150     EXPECT_EQ(off, 0);
151 }
152 
TEST(MemBlock,unallocate)153 TEST(MemBlock, unallocate) {
154     const struct address_space_device_control_ops ops =
155         create_address_space_device_control_ops();
156 
157     const AddressSpaceHwFuncs hw = create_AddressSpaceHwFuncs();
158 
159     MemBlock block(&ops, &hw, 100);
160     EXPECT_TRUE(block.isAllFree());
161     EXPECT_EQ(block.physBase, 2020 + 100 * 10);
162 
163     uint32_t off60 = block.allocate(60);
164     EXPECT_GE(off60, 2020 + 100 * 10);
165 
166     uint32_t off20 = block.allocate(20);
167     EXPECT_GE(off20, 2020 + 100 * 10);
168 
169     uint32_t off30 = block.allocate(30);
170     EXPECT_EQ(off30, 0);
171 
172     block.unallocate(off20, 20);
173 
174     off30 = block.allocate(30);
175     EXPECT_GE(off30, 2020 + 100 * 10);
176 
177     block.unallocate(off60, 60);
178     block.unallocate(off30, 30);
179 
180     EXPECT_TRUE(block.isAllFree());
181 }
182 
183 }  // namespace emulation
184 } // namespace android
185