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