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()
56 : Test(CHRE_API_VERSION_1_0) {
57 }
58
setUp(uint32_t messageSize,const void *)59 void SendEventStressTest::setUp(uint32_t messageSize,
60 const void * /* message */) {
61 sInMethod = true;
62
63 if (messageSize != 0) {
64 sendFatalFailureToHost(
65 "SendEventStress message expects 0 additional bytes, got ",
66 &messageSize);
67 }
68
69 mInstanceId = chreGetInstanceId();
70
71 // When our chreSendEvent() call fails, the CHRE is allowed to
72 // directly invoke our completeCallback. We special case this
73 // with sInitTime, so we can ignore sInMethod for that case only.
74 sCompleteCallbacksLeft = 1;
75 sInitTime = true;
76
77 // We anticipate most CHREs will not reach kMaxEventsToSend.
78 while ((sEventsLeft < kMaxEventsToSend) &&
79 chreSendEvent(kEventType, kEventData, completeCallback,
80 mInstanceId)) {
81 sEventsLeft++;
82 }
83 sInitTime = false;
84
85 // We want at least 2 events for this to pretend to be an exhaustion test.
86 if (sEventsLeft < 2) {
87 sendFatalFailureToHost("Insufficient events available");
88 }
89
90 // sCompleteCallbacksLeft may be 0 or 1 at this point. We don't care.
91 // We just know we also expect all the sEventsLeft to have callbacks.
92 sCompleteCallbacksLeft += sEventsLeft;
93
94 sInMethod = false;
95 }
96
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)97 void SendEventStressTest::handleEvent(uint32_t senderInstanceId,
98 uint16_t eventType,
99 const void* eventData) {
100 if (sInMethod) {
101 sendFatalFailureToHost("handleEvent invoked while another nanoapp "
102 "method is running");
103 }
104 sInMethod = true;
105 if (senderInstanceId != mInstanceId) {
106 sendFatalFailureToHost("handleEvent got event from unexpected sender:",
107 &senderInstanceId);
108 }
109 sanityCheck(eventType, eventData, 0);
110
111 --sEventsLeft;
112 if (sEventsLeft < 0) {
113 sendFatalFailureToHost("Too many events delivered");
114 }
115
116 sInMethod = false;
117 }
118
sanityCheck(uint16_t eventType,const void * data,uint32_t num)119 void SendEventStressTest::sanityCheck(uint16_t eventType, const void *data,
120 uint32_t num) {
121 if (eventType != kEventType) {
122 unexpectedEvent(eventType);
123 }
124 if (data != kEventData) {
125 // 0: handleEvent, 1: completeCallback
126 sendFatalFailureToHost("bad event data:", &num);
127 }
128 }
129
130
completeCallback(uint16_t eventType,void * data)131 void SendEventStressTest::completeCallback(uint16_t eventType, void *data) {
132 if (sInitTime) {
133 // The CHRE must be directly calling this from within
134 // chreSendEvent(), after it failed. We only allow a
135 // single one of these calls.
136 sInitTime = false;
137 sanityCheck(eventType, data, 1);
138 sCompleteCallbacksLeft--;
139 return;
140 }
141
142 if (sInMethod) {
143 sendFatalFailureToHost("completeCallback invoked while another nanoapp "
144 "method is running");
145 }
146 sanityCheck(eventType, data, 1);
147
148 --sCompleteCallbacksLeft;
149 if (sCompleteCallbacksLeft == 0) {
150 if (sEventsLeft != 0) {
151 sendFatalFailureToHost("completeCallbacks delivered before events");
152 }
153 sendSuccessToHost();
154 } else if (sCompleteCallbacksLeft < 0) {
155 // It's too late for the Host to catch this failure, but perhaps
156 // the abort will screw up our unload, and trigger a failure that way.
157 sendFatalFailureToHost("completeCallback called too many times");
158 }
159 }
160
161
162 } // namespace general_test
163