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_api/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   // If kMaxEventsToSend events are sent, we need to reset
88   // sCompleteCallbacksLeft because we only expect at most sEventsLeft to have
89   // callbacks.
90   if (sEventsLeft == kMaxEventsToSend) {
91     sCompleteCallbacksLeft = 0;
92   }
93   sCompleteCallbacksLeft += sEventsLeft;
94 
95   sInMethod = false;
96 }
97 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)98 void SendEventStressTest::handleEvent(uint32_t senderInstanceId,
99                                       uint16_t eventType,
100                                       const void *eventData) {
101   if (sInMethod) {
102     sendFatalFailureToHost(
103         "handleEvent invoked while another nanoapp method is running");
104   }
105   sInMethod = true;
106   if (senderInstanceId != mInstanceId) {
107     sendFatalFailureToHost("handleEvent got event from unexpected sender:",
108                            &senderInstanceId);
109   }
110   verifyEvent(eventType, eventData, 0);
111 
112   --sEventsLeft;
113   if (sEventsLeft < 0) {
114     sendFatalFailureToHost("Too many events delivered");
115   }
116 
117   sInMethod = false;
118 }
119 
verifyEvent(uint16_t eventType,const void * data,uint32_t num)120 void SendEventStressTest::verifyEvent(uint16_t eventType, const void *data,
121                                       uint32_t num) {
122   if (eventType != kEventType) {
123     unexpectedEvent(eventType);
124   }
125   if (data != kEventData) {
126     // 0: handleEvent, 1: completeCallback
127     sendFatalFailureToHost("bad event data:", &num);
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     verifyEvent(eventType, data, 1);
138     sCompleteCallbacksLeft--;
139     return;
140   }
141 
142   if (sInMethod) {
143     sendFatalFailureToHost(
144         "completeCallback invoked while another nanoapp method is running");
145   }
146   verifyEvent(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   } else if (sEventsLeft <= 0 && sCompleteCallbacksLeft > 0) {
159     sendFatalFailureToHost(
160         "completeCallback called less times than events sent");
161   }
162 }
163 
164 }  // namespace general_test
165