1 /* 2 * Copyright (C) 2016 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 <general_test/heap_exhaustion_stability_test.h> 18 19 #include <cinttypes> 20 #include <cstddef> 21 22 #include <shared/send_message.h> 23 24 #include <chre.h> 25 26 using nanoapp_testing::sendFailureToHost; 27 using nanoapp_testing::sendFatalFailureToHost; 28 using nanoapp_testing::sendSuccessToHost; 29 30 /* 31 * We set an "exhaustion timer" to go off when we're ready for the test to 32 * be over. Then we exhaust the heap. 33 * 34 * We try a series of chre*() calls with the heap exhausted. For many of 35 * these calls, we're less interested in them succeeding than in the system 36 * just not crashing. However, for things which claim success, we require 37 * they succeed. 38 * 39 * To track the things which claim success, we have two "stages", kTimerStage 40 * and kEventStage. 41 * 42 * When the "exhaustion timer" fires, we free our memory, and make sure our 43 * stages have all succeeded. 44 */ 45 46 namespace general_test { 47 48 // Note: We use pointers to the 'duration' to serve as our timer event data. 49 // Thus we make this "static const" instead of "constexpr", as we expect 50 // them to have backing memory. 51 52 // 5 seconds 53 static const uint64_t kExhaustionDuration = UINT64_C(5000000000); 54 // 10 milliseconds 55 static const uint64_t kShortDuration = UINT64_C(10000000); 56 57 constexpr uint16_t kEventType = CHRE_EVENT_FIRST_USER_VALUE; 58 59 constexpr uint32_t kTimerStage = 0; 60 constexpr uint32_t kEventStage = 1; 61 62 void HeapExhaustionStabilityTest::exhaustHeap() { 63 constexpr size_t kNumPtrs = 256; 64 mExhaustionPtrs = reinterpret_cast<void**>( 65 chreHeapAlloc(kNumPtrs * sizeof(*mExhaustionPtrs))); 66 if (mExhaustionPtrs == nullptr) { 67 // Oh, the irony. 68 sendFatalFailureToHost( 69 "Insufficient free heap to exhaust the heap."); 70 } 71 72 // We start by trying to allocate massive sizes (256MB to start). 73 // When we're not able to allocate massive sizes, we cut the size in 74 // half. We repeat until we've either done kNumPtrs allocations, 75 // or reduced our allocation size below 16 bytes. 76 uint32_t allocSize = 1024 * 1024 * 256; 77 for (mExhaustionPtrCount = 0; 78 mExhaustionPtrCount < kNumPtrs; 79 mExhaustionPtrCount++) { 80 void *ptr = chreHeapAlloc(allocSize); 81 while (ptr == nullptr) { 82 allocSize /= 2; 83 if (allocSize < 4) { 84 break; 85 } 86 ptr = chreHeapAlloc(allocSize); 87 } 88 if (ptr == nullptr) { 89 break; 90 } 91 mExhaustionPtrs[mExhaustionPtrCount] = ptr; 92 } 93 if (mExhaustionPtrCount == 0) { 94 sendFatalFailureToHost( 95 "Failed to allocate anything for heap exhaustion"); 96 } 97 } 98 99 void HeapExhaustionStabilityTest::freeMemory() { 100 for (size_t i = 0; i < mExhaustionPtrCount; i++) { 101 chreHeapFree(mExhaustionPtrs[i]); 102 } 103 chreHeapFree(mExhaustionPtrs); 104 } 105 106 HeapExhaustionStabilityTest::HeapExhaustionStabilityTest() 107 : Test(CHRE_API_VERSION_1_0) { 108 } 109 110 void HeapExhaustionStabilityTest::setUp(uint32_t messageSize, 111 const void * /* message */) { 112 mInMethod = true; 113 if (messageSize != 0) { 114 sendFatalFailureToHost( 115 "HeapExhaustionStability message expects 0 additional bytes, " 116 "got ", &messageSize); 117 } 118 119 if (chreTimerSet(kExhaustionDuration, &kExhaustionDuration, true) == 120 CHRE_TIMER_INVALID) { 121 sendFatalFailureToHost("Unable to set initial timer"); 122 } 123 124 exhaustHeap(); 125 126 testLog(messageSize); 127 testSetTimer(); 128 testSendEvent(); 129 testSensor(); 130 // TODO(b/32114261): This method currently doesn't test anything. 131 testMessageToHost(); 132 133 // Some of the above 'test' methods might trigger events. Even if they 134 // don't, the kExhaustionDuration timer we set earlier should trigger 135 // eventually, and that's when we'll conclude the test. 136 mInMethod = false; 137 } 138 139 void HeapExhaustionStabilityTest::testLog(uint32_t zero) { 140 // This doesn't need to land in the log (and indeed we have no automated 141 // means of checking that right now anyway), but it shouldn't crash. 142 chreLog(CHRE_LOG_INFO, "Test log %s, zero: %" PRId32, "message", zero); 143 } 144 145 void HeapExhaustionStabilityTest::testSetTimer() { 146 if (chreTimerSet(kShortDuration, &kShortDuration, true) != 147 CHRE_TIMER_INVALID) { 148 // CHRE claims we were able to set this timer. We'll 149 // mark this stage a success when the timer fires. 150 } else { 151 // CHRE was not able to set this timer. That's okay, since we're 152 // out of heap. We'll mark this stage as a success. 153 markSuccess(kTimerStage); 154 } 155 } 156 157 void HeapExhaustionStabilityTest::testSendEvent() { 158 if (chreSendEvent(kEventType, nullptr, nullptr, chreGetInstanceId())) { 159 // CHRE claims we were able to send this event. We'll make 160 // this stage a success when the event is received. 161 } else { 162 // CHRE was not able to send this event. That's okay, since we're 163 // out of heap. We'll mark this stage as a success. 164 markSuccess(kEventStage); 165 } 166 } 167 168 void HeapExhaustionStabilityTest::testSensor() { 169 static constexpr uint8_t kSensorType = CHRE_SENSOR_TYPE_ACCELEROMETER; 170 uint32_t handle; 171 if (!chreSensorFindDefault(kSensorType, &handle)) { 172 // We still expect this to succeed without any heap left. 173 sendFatalFailureToHost("chreSensorFindDefault failed"); 174 } 175 chreSensorInfo info; 176 if (!chreGetSensorInfo(handle, &info)) { 177 // We still expect this to succeed, since we're supplying the memory. 178 sendFatalFailureToHost("chreGetSensorInfo failed"); 179 } 180 if (info.sensorType != kSensorType) { 181 sendFatalFailureToHost("Invalid sensor info provided"); 182 } 183 184 chreSensorSamplingStatus samplingStatus; 185 if (!chreGetSensorSamplingStatus(handle, &samplingStatus)) { 186 // We still expect this to succeed, since we're supplying the memory. 187 sendFatalFailureToHost("chreGetSensorSamplingStatus failed"); 188 } 189 190 // TODO: We might want to consider calling chreSensorConfigure() for a 191 // more robust test of this. However, we don't expect sensor events to 192 // necessarily get delivered under heap exhaustion, so it's unclear 193 // how we'd make sure we eventually tell the system we're DONE with 194 // the sensor (setting a timer isn't assured to work at this point). 195 } 196 197 void HeapExhaustionStabilityTest::testMessageToHost() { 198 // TODO(b/32114261): We should invoke sendMessageToHost() here. 199 // Unfortunately, this is a real pain due to this bug, as we need to 200 // duplicate much of the contents of shared/send_message.cc to 201 // add the hack-around bytes (the method itself will internally 202 // fail if the send attempt fails, but we're in a state where 203 // we'll allow a failed send attempt). Or we need to take this 204 // off of the General test infrastructure to allow raw byte sending. 205 // That seems not worth the effort for NYC, and just easier to wait 206 // until OMC when this is much easier to implement. 207 // OMC Note: When we've fixed this bug, and added a send here, we'll 208 // need to make this no longer Simple protocol, since this nanoapp 209 // might send a message. 210 } 211 212 void HeapExhaustionStabilityTest::handleEvent(uint32_t senderInstanceId, 213 uint16_t eventType, 214 const void* eventData) { 215 if (mInMethod) { 216 sendFatalFailureToHost("handleEvent invoked while another nanoapp " 217 "method is running"); 218 } 219 mInMethod = true; 220 221 if (eventType == CHRE_EVENT_TIMER) { 222 handleTimer(senderInstanceId, eventData); 223 } else if (eventType == kEventType) { 224 handleSelfEvent(senderInstanceId, eventData); 225 } else { 226 unexpectedEvent(eventType); 227 } 228 mInMethod = false; 229 } 230 231 void HeapExhaustionStabilityTest::handleTimer(uint32_t senderInstanceId, 232 const void *eventData) { 233 if (senderInstanceId != CHRE_INSTANCE_ID) { 234 sendFatalFailureToHost("handleTimer with unexpected sender:", 235 &senderInstanceId); 236 } 237 if (eventData == &kShortDuration) { 238 // This was the timer we triggered while the heap was exhausted. 239 markSuccess(kTimerStage); 240 241 } else if (eventData == &kExhaustionDuration) { 242 // Our test is done. 243 freeMemory(); 244 if (mFinishedBitmask != kAllFinished) { 245 sendFatalFailureToHost("Done with test, but not all stages " 246 "done.", &mFinishedBitmask); 247 } 248 sendSuccessToHost(); 249 250 } else { 251 sendFatalFailureToHost("Unexpected timer eventData"); 252 } 253 } 254 255 void HeapExhaustionStabilityTest::handleSelfEvent(uint32_t senderInstanceId, 256 const void *eventData) { 257 if (senderInstanceId != chreGetInstanceId()) { 258 sendFatalFailureToHost("handleSelfEvent with unexpected sender:", 259 &senderInstanceId); 260 } 261 if (eventData != nullptr) { 262 sendFatalFailureToHost("Unexpected data for event to self"); 263 } 264 markSuccess(kEventStage); 265 } 266 267 void HeapExhaustionStabilityTest::markSuccess(uint32_t stage) { 268 chreLog(CHRE_LOG_DEBUG, "Stage %" PRIu32 " succeeded", stage); 269 uint32_t finishedBit = (1 << stage); 270 if ((kAllFinished & finishedBit) == 0) { 271 sendFatalFailureToHost("markSuccess bad stage", &stage); 272 } 273 if ((mFinishedBitmask & finishedBit) != 0) { 274 // This could be when a timer/event method returned 'false', but 275 // actually did end up triggering an event. 276 sendFatalFailureToHost("markSuccess stage triggered twice", &stage); 277 } 278 mFinishedBitmask |= finishedBit; 279 // Note that unlike many markSuccess() implementations, we do not 280 // check against kAllFinished here. That happens when the 281 // timer for kExhaustionDuration fires. 282 } 283 284 285 } // namespace general_test 286