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