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