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 <cstddef> // max_align_t
18 #include <cstdint>
19 #include <new> // placement new
20
21 #include <general_test/basic_audio_test.h>
22 #include <general_test/basic_ble_test.h>
23 #include <general_test/basic_flush_async_test.h>
24 #include <general_test/basic_gnss_test.h>
25 #include <general_test/basic_sensor_tests.h>
26 #include <general_test/basic_wifi_test.h>
27 #include <general_test/estimated_host_time_test.h>
28 #include <general_test/event_between_apps_test.h>
29 #include <general_test/get_time_test.h>
30 #include <general_test/gnss_capabilities_test.h>
31 #include <general_test/heap_alloc_stress_test.h>
32 #include <general_test/heap_exhaustion_stability_test.h>
33 #include <general_test/hello_world_test.h>
34 #include <general_test/host_awake_suspend_test.h>
35 #include <general_test/logging_consistency_test.h>
36 #include <general_test/nanoapp_info_by_app_id_test.h>
37 #include <general_test/nanoapp_info_by_instance_id_test.h>
38 #include <general_test/nanoapp_info_events_test_observer.h>
39 #include <general_test/nanoapp_info_events_test_performer.h>
40 #include <general_test/send_event_stress_test.h>
41 #include <general_test/send_event_test.h>
42 #include <general_test/send_message_to_host_test.h>
43 #include <general_test/sensor_info_test.h>
44 #include <general_test/simple_heap_alloc_test.h>
45 #include <general_test/test.h>
46 #include <general_test/test_names.h>
47 #include <general_test/timer_cancel_test.h>
48 #include <general_test/timer_set_test.h>
49 #include <general_test/timer_stress_test.h>
50 #include <general_test/version_consistency_test.h>
51 #include <general_test/wifi_capabilities_test.h>
52 #include <general_test/wwan_capabilities_test.h>
53 #include <general_test/wwan_cell_info_test.h>
54 #include <shared/abort.h>
55 #include <shared/nano_endian.h>
56 #include <shared/nano_string.h>
57 #include <shared/send_message.h>
58
59 #include "chre_api/chre.h"
60
61 using nanoapp_testing::AbortBlame;
62 using nanoapp_testing::MessageType;
63 using nanoapp_testing::sendFatalFailureToHost;
64 using nanoapp_testing::sendInternalFailureToHost;
65
66 namespace general_test {
67
68 // The size of this array is checked at compile time by the static_assert
69 // in getNew().
70 alignas(alignof(max_align_t)) static uint8_t gGetNewBackingMemory[128];
71
72 template <typename N>
getNew()73 static N *getNew() {
74 // We intentionally avoid using chreHeapAlloc() to reduce dependencies
75 // for our tests, especially things like HelloWorld. This obviously
76 // cannot be called more than once, but our usage doesn't require it.
77 static_assert(sizeof(gGetNewBackingMemory) >= sizeof(N),
78 "getNew() backing memory is undersized");
79
80 return new (gGetNewBackingMemory) N();
81 }
82
83 // TODO(b/32114261): Remove this variable.
84 bool gUseNycMessageHack = true;
85
86 class App {
87 public:
App()88 App() : mConstructionCookie(kConstructed), mCurrentTest(nullptr) {}
89
~App()90 ~App() {
91 // Yes, it's very odd to actively set a value in our destructor.
92 // However, since we're making a static instance of this class,
93 // the space for this class will stick around (unlike heap memory
94 // which might get reused), so we can still use this to perform
95 // some testing.
96 mConstructionCookie = kDestructed;
97 }
98
wasConstructed() const99 bool wasConstructed() const {
100 return mConstructionCookie == kConstructed;
101 }
wasDestructed() const102 bool wasDestructed() const {
103 return mConstructionCookie == kDestructed;
104 }
105
106 void handleEvent(uint32_t senderInstanceId, uint16_t eventType,
107 const void *eventData);
108
109 void createTest(const void *eventData);
110 void freeTest();
111
112 private:
113 uint32_t mConstructionCookie;
114 Test *mCurrentTest;
115
116 static constexpr uint32_t kConstructed = UINT32_C(0x51501984);
117 static constexpr uint32_t kDestructed = UINT32_C(0x19845150);
118
119 // TODO(b/32114261): Remove this method.
120 chreMessageFromHostData adjustHostMessageForNYC(
121 const chreMessageFromHostData *data);
122 };
123
124 // In the NYC version of the CHRE, the "reservedMessageType" isn't
125 // assured to be sent correctly from the host. But we want our
126 // tests to be written using this field (it's cleaner). So in NYC
127 // the host prefixes this value in the first four bytes of 'message',
128 // and here we reconstruct the message to be correct.
129 // TODO(b/32114261): Remove this method.
adjustHostMessageForNYC(const chreMessageFromHostData * data)130 chreMessageFromHostData App::adjustHostMessageForNYC(
131 const chreMessageFromHostData *data) {
132 if (!gUseNycMessageHack) {
133 return *data;
134 }
135 chreMessageFromHostData ret;
136
137 if (data->messageSize < sizeof(uint32_t)) {
138 sendFatalFailureToHost("Undersized message in adjustHostMessageForNYC");
139 }
140 const uint8_t *messageBytes = static_cast<const uint8_t *>(data->message);
141 nanoapp_testing::memcpy(&(ret.reservedMessageType), messageBytes,
142 sizeof(ret.reservedMessageType));
143 ret.reservedMessageType =
144 nanoapp_testing::littleEndianToHost(ret.reservedMessageType);
145 ret.messageSize = data->messageSize - sizeof(ret.reservedMessageType);
146 ret.message = messageBytes + sizeof(ret.reservedMessageType);
147 return ret;
148 }
149
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)150 void App::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
151 const void *eventData) {
152 // TODO: When we get an API that fixes the reservedMessageType,
153 // then we should only use our adjustedData hack on APIs
154 // prior to it being fixed. Eventually, we should remove
155 // this altogether.
156 chreMessageFromHostData adjustedData;
157 if (eventType == CHRE_EVENT_MESSAGE_FROM_HOST) {
158 auto data = static_cast<const chreMessageFromHostData *>(eventData);
159 adjustedData = adjustHostMessageForNYC(data);
160 eventData = &adjustedData;
161 }
162
163 if (mCurrentTest != nullptr) {
164 // Our test is in progress, so let it take control.
165 mCurrentTest->testHandleEvent(senderInstanceId, eventType, eventData);
166 return;
167 }
168
169 // No test in progress, so we expect this message to be the host telling
170 // us which test to run. We fail if it's anything else.
171 if (eventType != CHRE_EVENT_MESSAGE_FROM_HOST) {
172 uint32_t localEventType = eventType;
173 sendFatalFailureToHost("Unexpected event type with no established test:",
174 &localEventType);
175 }
176 if (senderInstanceId != CHRE_INSTANCE_ID) {
177 sendFatalFailureToHost("Got MESSAGE_FROM_HOST not from CHRE_INSTANCE_ID:",
178 &senderInstanceId);
179 }
180 createTest(eventData);
181 }
182
createTest(const void * eventData)183 void App::createTest(const void *eventData) {
184 if (mCurrentTest != nullptr) {
185 sendInternalFailureToHost("Got to createTest() with non-null mCurrentTest");
186 }
187
188 auto data = static_cast<const chreMessageFromHostData *>(eventData);
189
190 switch (static_cast<TestNames>(data->reservedMessageType)) {
191 using namespace general_test;
192
193 #define CASE(testName, className) \
194 case TestNames::testName: \
195 mCurrentTest = getNew<className>(); \
196 break;
197
198 CASE(kHelloWorld, HelloWorldTest);
199 CASE(kSimpleHeapAlloc, SimpleHeapAllocTest);
200 CASE(kHeapAllocStress, HeapAllocStressTest);
201 CASE(kGetTime, GetTimeTest);
202 CASE(kEventBetweenApps0, EventBetweenApps0);
203 CASE(kEventBetweenApps1, EventBetweenApps1);
204 CASE(kSendEvent, SendEventTest);
205 CASE(kBasicAccelerometer, BasicAccelerometerTest);
206 CASE(kBasicInstantMotionDetect, BasicInstantMotionDetectTest);
207 CASE(kBasicStationaryDetect, BasicStationaryDetectTest);
208 CASE(kBasicGyroscope, BasicGyroscopeTest);
209 CASE(kBasicMagnetometer, BasicMagnetometerTest);
210 CASE(kBasicBarometer, BasicBarometerTest);
211 CASE(kBasicLightSensor, BasicLightSensorTest);
212 CASE(kBasicProximity, BasicProximityTest);
213 CASE(kVersionConsistency, VersionConsistencyTest);
214 CASE(kLoggingConsistency, LoggingConsistencyTest);
215 CASE(kSendMessageToHost, SendMessageToHostTest);
216 CASE(kTimerSet, TimerSetTest);
217 CASE(kTimerCancel, TimerCancelTest);
218 CASE(kTimerStress, TimerStressTest);
219 CASE(kSendEventStress, SendEventStressTest);
220 CASE(kHeapExhaustionStability, HeapExhaustionStabilityTest);
221 CASE(kGnssCapabilities, GnssCapabilitiesTest);
222 CASE(kWifiCapabilities, WifiCapabilitiesTest);
223 CASE(kWwanCapabilities, WwanCapabilitiesTest);
224 CASE(kSensorInfo, SensorInfoTest);
225 CASE(kWwanCellInfoTest, WwanCellInfoTest);
226 CASE(kEstimatedHostTime, EstimatedHostTimeTest);
227 CASE(kNanoappInfoByAppId, NanoappInfoByAppIdTest);
228 CASE(kNanoappInfoByInstanceId, NanoappInfoByInstanceIdTest);
229 CASE(kNanoAppInfoEventsPerformer, NanoAppInfoEventsTestPerformer);
230 CASE(kNanoAppInfoEventsObserver, NanoAppInfoEventsTestObserver);
231 CASE(kBasicAudioTest, BasicAudioTest);
232 CASE(kHostAwakeSuspend, HostAwakeSuspendTest);
233 CASE(kBasicGnssTest, BasicGnssTest);
234 CASE(kBasicWifiTest, BasicWifiTest);
235 CASE(kBasicSensorFlushAsyncTest, BasicSensorFlushAsyncTest);
236 CASE(kBasicBleTest, BasicBleTest);
237
238 #undef CASE
239
240 default:
241 sendFatalFailureToHost("Unexpected message type:",
242 &(data->reservedMessageType));
243 }
244
245 if (mCurrentTest != nullptr) {
246 mCurrentTest->testSetUp(data->messageSize, data->message);
247 } else {
248 sendInternalFailureToHost("createTest() ended with null mCurrentTest");
249 }
250 }
251
freeTest()252 void App::freeTest() {
253 if (mCurrentTest == nullptr) {
254 sendInternalFailureToHost("Nanoapp unloading without running any test");
255 }
256 mCurrentTest->~Test();
257 }
258
259 } // namespace general_test
260
261 static general_test::App gApp;
262
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)263 extern "C" void nanoappHandleEvent(uint32_t senderInstanceId,
264 uint16_t eventType, const void *eventData) {
265 gApp.handleEvent(senderInstanceId, eventType, eventData);
266 }
267
268 static uint32_t zeroedBytes[13];
269
nanoappStart(void)270 extern "C" bool nanoappStart(void) {
271 // zeroedBytes is in the BSS and needs to be zero'd out.
272 for (size_t i = 0; i < sizeof(zeroedBytes) / sizeof(zeroedBytes[0]); i++) {
273 if (zeroedBytes[i] != 0) {
274 return false;
275 }
276 }
277
278 // A CHRE is required to call the constructor of our class prior to
279 // reaching this point.
280 return gApp.wasConstructed();
281 }
282
nanoappEnd(void)283 extern "C" void nanoappEnd(void) {
284 if (gApp.wasDestructed()) {
285 // It's not legal for us to send a message from here. The best
286 // we can do is abort, although there's no means for the end user
287 // to see such a failure.
288 // TODO: Figure out how to have this failure noticed.
289 nanoapp_testing::abort(AbortBlame::kChreInNanoappEnd);
290 }
291 gApp.freeTest();
292
293 // TODO: Unclear how we can test the global destructor being called,
294 // but that would be good to test. Since it's supposed to happen
295 // after this call completes, it's difficult to test.
296 }
297