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/send_event_stress_test.h>
18
19 #include <cstddef>
20
21 #include <shared/send_message.h>
22
23 #include <chre.h>
24
25 using nanoapp_testing::sendFatalFailureToHost;
26 using nanoapp_testing::sendSuccessToHost;
27
28 /*
29 * We stress the system by sending more and more events until it runs out.
30 * Then we wait for all the events to be delivered, and all the completion
31 * callbacks to be invoked.
32 */
33
34 constexpr uint16_t kEventType = CHRE_EVENT_FIRST_USER_VALUE;
35 void *const kEventData = reinterpret_cast<void *>(-1);
36
37 // If the system keeps claiming it can send more events, we don't let it
38 // continue forever. Instead, we'll cut it off at this limit. And then
39 // we'll call its bluff, and make sure that all of these events get
40 // delivered. While it won't be an actual exhaustion test (we never took the
41 // system down to no more events available), it will still give us confidence
42 // that this CHRE can properly handle any semi-reasonable event load properly.
43 // 1030 is an arbitrary number, slightly over 2^10. The hope is this
44 // balances between catching incorrect behavior and the test taking too long.
45 constexpr int32_t kMaxEventsToSend = INT32_C(1030);
46
47 namespace general_test {
48
49 bool SendEventStressTest::sInMethod = false;
50 bool SendEventStressTest::sInitTime = false;
51
52 int32_t SendEventStressTest::sEventsLeft = 0;
53 int32_t SendEventStressTest::sCompleteCallbacksLeft = 0;
54
SendEventStressTest()55 SendEventStressTest::SendEventStressTest() : Test(CHRE_API_VERSION_1_0) {}
56
setUp(uint32_t messageSize,const void *)57 void SendEventStressTest::setUp(uint32_t messageSize,
58 const void * /* message */) {
59 sInMethod = true;
60
61 if (messageSize != 0) {
62 sendFatalFailureToHost(
63 "SendEventStress message expects 0 additional bytes, got ",
64 &messageSize);
65 }
66
67 mInstanceId = chreGetInstanceId();
68
69 // When our chreSendEvent() call fails, the CHRE is allowed to
70 // directly invoke our completeCallback. We special case this
71 // with sInitTime, so we can ignore sInMethod for that case only.
72 sCompleteCallbacksLeft = 1;
73 sInitTime = true;
74
75 // We anticipate most CHREs will not reach kMaxEventsToSend.
76 while ((sEventsLeft < kMaxEventsToSend) &&
77 chreSendEvent(kEventType, kEventData, completeCallback, mInstanceId)) {
78 sEventsLeft++;
79 }
80 sInitTime = false;
81
82 // We want at least 2 events for this to pretend to be an exhaustion test.
83 if (sEventsLeft < 2) {
84 sendFatalFailureToHost("Insufficient events available");
85 }
86
87 // sCompleteCallbacksLeft may be 0 or 1 at this point. We don't care.
88 // We just know we also expect all the sEventsLeft to have callbacks.
89 sCompleteCallbacksLeft += sEventsLeft;
90
91 sInMethod = false;
92 }
93
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)94 void SendEventStressTest::handleEvent(uint32_t senderInstanceId,
95 uint16_t eventType,
96 const void *eventData) {
97 if (sInMethod) {
98 sendFatalFailureToHost(
99 "handleEvent invoked while another nanoapp method is running");
100 }
101 sInMethod = true;
102 if (senderInstanceId != mInstanceId) {
103 sendFatalFailureToHost("handleEvent got event from unexpected sender:",
104 &senderInstanceId);
105 }
106 verifyEvent(eventType, eventData, 0);
107
108 --sEventsLeft;
109 if (sEventsLeft < 0) {
110 sendFatalFailureToHost("Too many events delivered");
111 }
112
113 sInMethod = false;
114 }
115
verifyEvent(uint16_t eventType,const void * data,uint32_t num)116 void SendEventStressTest::verifyEvent(uint16_t eventType, const void *data,
117 uint32_t num) {
118 if (eventType != kEventType) {
119 unexpectedEvent(eventType);
120 }
121 if (data != kEventData) {
122 // 0: handleEvent, 1: completeCallback
123 sendFatalFailureToHost("bad event data:", &num);
124 }
125 }
126
completeCallback(uint16_t eventType,void * data)127 void SendEventStressTest::completeCallback(uint16_t eventType, void *data) {
128 if (sInitTime) {
129 // The CHRE must be directly calling this from within
130 // chreSendEvent(), after it failed. We only allow a
131 // single one of these calls.
132 sInitTime = false;
133 verifyEvent(eventType, data, 1);
134 sCompleteCallbacksLeft--;
135 return;
136 }
137
138 if (sInMethod) {
139 sendFatalFailureToHost(
140 "completeCallback invoked while another nanoapp method is running");
141 }
142 verifyEvent(eventType, data, 1);
143
144 --sCompleteCallbacksLeft;
145 if (sCompleteCallbacksLeft == 0) {
146 if (sEventsLeft != 0) {
147 sendFatalFailureToHost("completeCallbacks delivered before events");
148 }
149 sendSuccessToHost();
150 } else if (sCompleteCallbacksLeft < 0) {
151 // It's too late for the Host to catch this failure, but perhaps
152 // the abort will screw up our unload, and trigger a failure that way.
153 sendFatalFailureToHost("completeCallback called too many times");
154 }
155 }
156
157 } // namespace general_test
158