1 /*
2 * Copyright (C) 2022 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 "chre_api/chre/re.h"
18
19 #include <cstdint>
20
21 #include "chre/core/event_loop_manager.h"
22 #include "chre/platform/log.h"
23 #include "chre/platform/memory_manager.h"
24 #include "chre_api/chre/event.h"
25
26 #include "gtest/gtest.h"
27 #include "inc/test_util.h"
28 #include "test_base.h"
29 #include "test_event.h"
30 #include "test_event_queue.h"
31 #include "test_util.h"
32
33 namespace chre {
34 namespace {
35
getNanoappByAppId(uint64_t id)36 Nanoapp *getNanoappByAppId(uint64_t id) {
37 uint16_t instanceId;
38 EXPECT_TRUE(EventLoopManagerSingleton::get()
39 ->getEventLoop()
40 .findNanoappInstanceIdByAppId(id, &instanceId));
41 Nanoapp *nanoapp =
42 EventLoopManagerSingleton::get()->getEventLoop().findNanoappByInstanceId(
43 instanceId);
44 EXPECT_NE(nanoapp, nullptr);
45 return nanoapp;
46 }
47
TEST_F(TestBase,MemoryAllocateAndFree)48 TEST_F(TestBase, MemoryAllocateAndFree) {
49 CREATE_CHRE_TEST_EVENT(ALLOCATE, 0);
50 CREATE_CHRE_TEST_EVENT(FREE, 1);
51
52 struct App : public TestNanoapp {
53 void (*handleEvent)(uint32_t, uint16_t, const void *) =
54 [](uint32_t, uint16_t eventType, const void *eventData) {
55 switch (eventType) {
56 case CHRE_EVENT_TEST_EVENT: {
57 auto event = static_cast<const TestEvent *>(eventData);
58 switch (event->type) {
59 case ALLOCATE: {
60 auto bytes = static_cast<const uint32_t *>(event->data);
61 void *ptr = chreHeapAlloc(*bytes);
62 TestEventQueueSingleton::get()->pushEvent(ALLOCATE, ptr);
63 break;
64 }
65 case FREE: {
66 auto ptr = static_cast<void **>(event->data);
67 chreHeapFree(*ptr);
68 TestEventQueueSingleton::get()->pushEvent(FREE);
69 break;
70 }
71 }
72 }
73 }
74 };
75 };
76
77 auto app = loadNanoapp<App>();
78
79 MemoryManager &memManager =
80 EventLoopManagerSingleton::get()->getMemoryManager();
81 Nanoapp *nanoapp = getNanoappByAppId(app.id);
82
83 EXPECT_EQ(nanoapp->getTotalAllocatedBytes(), 0);
84 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 0);
85 EXPECT_EQ(memManager.getAllocationCount(), 0);
86
87 void *ptr1;
88 sendEventToNanoapp(app, ALLOCATE, 100);
89 waitForEvent(ALLOCATE, &ptr1);
90 EXPECT_NE(ptr1, nullptr);
91 EXPECT_EQ(nanoapp->getTotalAllocatedBytes(), 100);
92 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 100);
93 EXPECT_EQ(memManager.getAllocationCount(), 1);
94
95 void *ptr2;
96 sendEventToNanoapp(app, ALLOCATE, 200);
97 waitForEvent(ALLOCATE, &ptr2);
98 EXPECT_NE(ptr2, nullptr);
99 EXPECT_EQ(nanoapp->getTotalAllocatedBytes(), 100 + 200);
100 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 100 + 200);
101 EXPECT_EQ(memManager.getAllocationCount(), 2);
102
103 sendEventToNanoapp(app, FREE, ptr1);
104 waitForEvent(FREE);
105 EXPECT_EQ(nanoapp->getTotalAllocatedBytes(), 200);
106 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 200);
107 EXPECT_EQ(memManager.getAllocationCount(), 1);
108
109 sendEventToNanoapp(app, FREE, ptr2);
110 waitForEvent(FREE);
111 EXPECT_EQ(nanoapp->getTotalAllocatedBytes(), 0);
112 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 0);
113 EXPECT_EQ(memManager.getAllocationCount(), 0);
114 }
115
TEST_F(TestBase,MemoryFreeOnNanoappUnload)116 TEST_F(TestBase, MemoryFreeOnNanoappUnload) {
117 CREATE_CHRE_TEST_EVENT(ALLOCATE, 0);
118
119 struct App : public TestNanoapp {
120 void (*handleEvent)(uint32_t, uint16_t, const void *) =
121 [](uint32_t, uint16_t eventType, const void *eventData) {
122 switch (eventType) {
123 case CHRE_EVENT_TEST_EVENT: {
124 auto event = static_cast<const TestEvent *>(eventData);
125 switch (event->type) {
126 case ALLOCATE: {
127 auto bytes = static_cast<const uint32_t *>(event->data);
128 void *ptr = chreHeapAlloc(*bytes);
129 TestEventQueueSingleton::get()->pushEvent(ALLOCATE, ptr);
130 break;
131 }
132 }
133 }
134 }
135 };
136 };
137
138 auto app = loadNanoapp<App>();
139
140 MemoryManager &memManager =
141 EventLoopManagerSingleton::get()->getMemoryManager();
142 Nanoapp *nanoapp = getNanoappByAppId(app.id);
143
144 EXPECT_EQ(nanoapp->getTotalAllocatedBytes(), 0);
145 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 0);
146 EXPECT_EQ(memManager.getAllocationCount(), 0);
147
148 void *ptr1;
149 sendEventToNanoapp(app, ALLOCATE, 100);
150 waitForEvent(ALLOCATE, &ptr1);
151 EXPECT_NE(ptr1, nullptr);
152 EXPECT_EQ(nanoapp->getTotalAllocatedBytes(), 100);
153 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 100);
154 EXPECT_EQ(memManager.getAllocationCount(), 1);
155
156 void *ptr2;
157 sendEventToNanoapp(app, ALLOCATE, 200);
158 waitForEvent(ALLOCATE, &ptr2);
159 EXPECT_NE(ptr2, nullptr);
160 EXPECT_EQ(nanoapp->getTotalAllocatedBytes(), 100 + 200);
161 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 100 + 200);
162 EXPECT_EQ(memManager.getAllocationCount(), 2);
163
164 unloadNanoapp(app);
165 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 0);
166 EXPECT_EQ(memManager.getAllocationCount(), 0);
167 }
168
TEST_F(TestBase,MemoryStressTestShouldNotTriggerErrors)169 TEST_F(TestBase, MemoryStressTestShouldNotTriggerErrors) {
170 CREATE_CHRE_TEST_EVENT(ALLOCATE, 0);
171 CREATE_CHRE_TEST_EVENT(FREE, 1);
172
173 struct App : public TestNanoapp {
174 void (*handleEvent)(uint32_t, uint16_t, const void *) =
175 [](uint32_t, uint16_t eventType, const void *eventData) {
176 switch (eventType) {
177 case CHRE_EVENT_TEST_EVENT: {
178 auto event = static_cast<const TestEvent *>(eventData);
179 switch (event->type) {
180 case ALLOCATE: {
181 auto bytes = static_cast<const uint32_t *>(event->data);
182 void *ptr = chreHeapAlloc(*bytes);
183 TestEventQueueSingleton::get()->pushEvent(ALLOCATE, ptr);
184 break;
185 }
186 case FREE: {
187 auto ptr = static_cast<void **>(event->data);
188 chreHeapFree(*ptr);
189 TestEventQueueSingleton::get()->pushEvent(FREE);
190 break;
191 }
192 }
193 }
194 }
195 };
196 };
197
198 MemoryManager &memManager =
199 EventLoopManagerSingleton::get()->getMemoryManager();
200
201 auto app = loadNanoapp<App>();
202
203 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 0);
204 EXPECT_EQ(memManager.getAllocationCount(), 0);
205
206 void *ptr1;
207 void *ptr2;
208 void *ptr3;
209
210 sendEventToNanoapp(app, ALLOCATE, 100);
211 waitForEvent(ALLOCATE, &ptr1);
212 sendEventToNanoapp(app, ALLOCATE, 200);
213 waitForEvent(ALLOCATE, &ptr2);
214 sendEventToNanoapp(app, ALLOCATE, 300);
215 waitForEvent(ALLOCATE, &ptr3);
216 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 100 + 200 + 300);
217 EXPECT_EQ(memManager.getAllocationCount(), 3);
218
219 // Free middle, last, and first blocks.
220 sendEventToNanoapp(app, FREE, ptr2);
221 waitForEvent(FREE);
222 sendEventToNanoapp(app, FREE, ptr3);
223 waitForEvent(FREE);
224 sendEventToNanoapp(app, FREE, ptr1);
225 waitForEvent(FREE);
226 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 0);
227 EXPECT_EQ(memManager.getAllocationCount(), 0);
228
229 sendEventToNanoapp(app, ALLOCATE, 100);
230 waitForEvent(ALLOCATE, &ptr1);
231 sendEventToNanoapp(app, ALLOCATE, 200);
232 waitForEvent(ALLOCATE, &ptr2);
233 sendEventToNanoapp(app, ALLOCATE, 300);
234 waitForEvent(ALLOCATE, &ptr3);
235 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 100 + 200 + 300);
236 EXPECT_EQ(memManager.getAllocationCount(), 3);
237
238 // Free last, last and last blocks.
239 sendEventToNanoapp(app, FREE, ptr3);
240 waitForEvent(FREE);
241 sendEventToNanoapp(app, FREE, ptr2);
242 waitForEvent(FREE);
243 sendEventToNanoapp(app, FREE, ptr1);
244 waitForEvent(FREE);
245 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 0);
246 EXPECT_EQ(memManager.getAllocationCount(), 0);
247
248 sendEventToNanoapp(app, ALLOCATE, 100);
249 waitForEvent(ALLOCATE, &ptr1);
250 sendEventToNanoapp(app, ALLOCATE, 200);
251 waitForEvent(ALLOCATE, &ptr2);
252 sendEventToNanoapp(app, ALLOCATE, 300);
253 waitForEvent(ALLOCATE, &ptr3);
254 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 100 + 200 + 300);
255 EXPECT_EQ(memManager.getAllocationCount(), 3);
256
257 // Automatic cleanup.
258 unloadNanoapp(app);
259 EXPECT_EQ(memManager.getTotalAllocatedBytes(), 0);
260 EXPECT_EQ(memManager.getAllocationCount(), 0);
261 }
262
263 } // namespace
264 } // namespace chre