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_test.h>
18 
19 #include <cstddef>
20 
21 #include <shared/abort.h>
22 #include <shared/array_length.h>
23 #include <shared/send_message.h>
24 
25 #include <chre.h>
26 
27 using nanoapp_testing::sendFatalFailureToHost;
28 using nanoapp_testing::sendSuccessToHost;
29 
30 /*
31  * In a properly running test, we'll invoke chreSendEvent() a total of 12 times.
32  * We initially send eight events upon startup.  And then for each of our four
33  * events which has a non-nullptr completeCallback, we call chreSendEvent()
34  * from that callback.
35  *
36  * For our first eight events, they will either be kEventType0 or kEventType1.
37  * They will either use completeCallback0 or completeCallback1.  They have
38  * various data.  This table describes them all:
39  *
40  * num | eventType | data       | Callback
41  * ----|-----------|------------|---------
42  * 0   | 0         | ptr to num | 0
43  * 1   | 0         | ptr to num | 1
44  * 2   | 1         | ptr to num | 0
45  * 3   | 1         | ptr to num | 1
46  * 4   | 0         | ptr to num | nullptr
47  * 5   | 1         | ptr to num | nullptr
48  * 6   | 0         | nullptr    | nullptr
49  * 7   | 1         | kOddData   | nullptr
50  *
51  * The other four events are all kEventTypeCallback with nullptr data and
52  * nullptr callback.
53  */
54 
55 constexpr uint16_t kEventType0 = CHRE_EVENT_FIRST_USER_VALUE + 0;
56 constexpr uint16_t kEventType1 = CHRE_EVENT_FIRST_USER_VALUE + 1;
57 constexpr uint16_t kEventTypeCallback = CHRE_EVENT_FIRST_USER_VALUE + 2;
58 
59 // NOTE: This is not allowed to be constexpr, even if some version of g++/clang
60 //     allow it.
61 static void *kOddData = reinterpret_cast<void *>(-1);
62 
63 namespace general_test {
64 
65 bool SendEventTest::sInMethod = false;
66 uint8_t SendEventTest::sCallbacksInvoked = 0;
67 
68 template <uint8_t kCallbackIndex>
completeCallback(uint16_t eventType,void * data)69 void SendEventTest::completeCallback(uint16_t eventType, void *data) {
70   if (sInMethod) {
71     sendFatalFailureToHost(
72         "completeCallback called while another nanoapp method is running.");
73   }
74   sInMethod = true;
75   if ((data == nullptr) || (data == kOddData)) {
76     sendFatalFailureToHost("completeCallback called with nullptr or odd data.");
77   }
78   uint32_t num = *(reinterpret_cast<uint32_t *>(data));
79   uint16_t expectedEventType = 0xFFFF;
80   uint8_t expectedCallbackIndex = 0xFF;
81   switch (num) {
82     case 0:
83       expectedEventType = kEventType0;
84       expectedCallbackIndex = 0;
85       break;
86     case 1:
87       expectedEventType = kEventType0;
88       expectedCallbackIndex = 1;
89       break;
90     case 2:
91       expectedEventType = kEventType1;
92       expectedCallbackIndex = 0;
93       break;
94     case 3:
95       expectedEventType = kEventType1;
96       expectedCallbackIndex = 1;
97       break;
98     default:
99       sendFatalFailureToHost("completeCallback given bad data.", &num);
100   }
101   if (expectedEventType != eventType) {
102     sendFatalFailureToHost("completeCallback bad/eventType mismatch.");
103   }
104   if (expectedCallbackIndex != kCallbackIndex) {
105     sendFatalFailureToHost("Incorrect callback function called.");
106   }
107   uint8_t mask = static_cast<uint8_t>(1 << num);
108   if ((sCallbacksInvoked & mask) != 0) {
109     sendFatalFailureToHost("Complete callback invoked multiple times for ",
110                            &num);
111   }
112   sCallbacksInvoked |= mask;
113 
114   if (!chreSendEvent(kEventTypeCallback, nullptr, nullptr,
115                      chreGetInstanceId())) {
116     sendFatalFailureToHost("Failed chreSendEvent in callback.");
117   }
118   sInMethod = false;
119 }
120 
completeCallback0(uint16_t eventType,void * data)121 void SendEventTest::completeCallback0(uint16_t eventType, void *data) {
122   completeCallback<0>(eventType, data);
123 }
124 
completeCallback1(uint16_t eventType,void * data)125 void SendEventTest::completeCallback1(uint16_t eventType, void *data) {
126   completeCallback<1>(eventType, data);
127 }
128 
SendEventTest()129 SendEventTest::SendEventTest() : Test(CHRE_API_VERSION_1_0), mNextNum(0) {}
130 
setUp(uint32_t messageSize,const void *)131 void SendEventTest::setUp(uint32_t messageSize, const void * /* message */) {
132   sInMethod = true;
133   if (messageSize != 0) {
134     sendFatalFailureToHost("SendEvent message expects 0 additional bytes, got ",
135                            &messageSize);
136   }
137 
138   const uint32_t id = chreGetInstanceId();
139   for (uint32_t i = 0; i < arrayLength(mData); i++) {
140     mData[i] = i;
141   }
142 
143   // num: 0
144   if (!chreSendEvent(kEventType0, &mData[0], completeCallback0, id)) {
145     sendFatalFailureToHost("Failed chreSendEvent num 0");
146   }
147 
148   // num: 1
149   if (!chreSendEvent(kEventType0, &mData[1], completeCallback1, id)) {
150     sendFatalFailureToHost("Failed chreSendEvent num 1");
151   }
152 
153   // num: 2
154   if (!chreSendEvent(kEventType1, &mData[2], completeCallback0, id)) {
155     sendFatalFailureToHost("Failed chreSendEvent num 2");
156   }
157 
158   // num: 3
159   if (!chreSendEvent(kEventType1, &mData[3], completeCallback1, id)) {
160     sendFatalFailureToHost("Failed chreSendEvent num 3");
161   }
162 
163   // num: 4
164   if (!chreSendEvent(kEventType0, &mData[4], nullptr, id)) {
165     sendFatalFailureToHost("Failed chreSendEvent num 4");
166   }
167 
168   // num: 5
169   if (!chreSendEvent(kEventType1, &mData[5], nullptr, id)) {
170     sendFatalFailureToHost("Failed chreSendEvent num 5");
171   }
172 
173   // num: 6
174   if (!chreSendEvent(kEventType0, nullptr, nullptr, id)) {
175     sendFatalFailureToHost("Failed chreSendEvent num 6");
176   }
177 
178   // num: 7
179   if (!chreSendEvent(kEventType1, kOddData, nullptr, id)) {
180     sendFatalFailureToHost("Failed chreSendEvent num 7");
181   }
182 
183   sInMethod = false;
184 }
185 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)186 void SendEventTest::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
187                                 const void *eventData) {
188   if (sInMethod) {
189     sendFatalFailureToHost(
190         "handleEvent invoked while another nanoapp method is running");
191   }
192   sInMethod = true;
193   if (senderInstanceId != chreGetInstanceId()) {
194     sendFatalFailureToHost("handleEvent got event from unexpected sender:",
195                            &senderInstanceId);
196   }
197 
198   if (mNextNum < 8) {
199     void *expectedData;
200     if (mNextNum < 6) {
201       expectedData = &mData[mNextNum];
202     } else if (mNextNum == 6) {
203       expectedData = nullptr;
204     } else {
205       expectedData = kOddData;
206     }
207 
208     uint16_t expectedEventType = 0xFFFF;
209     switch (mNextNum) {
210       case 0:
211       case 1:
212       case 4:
213       case 6:
214         expectedEventType = kEventType0;
215         break;
216       case 2:
217       case 3:
218       case 5:
219       case 7:
220         expectedEventType = kEventType1;
221         break;
222     }
223 
224     if (expectedEventType != eventType) {
225       sendFatalFailureToHost("Incorrect event type sent for num ", &mNextNum);
226     }
227     if (expectedData != eventData) {
228       sendFatalFailureToHost("Incorrect data sent for num ", &mNextNum);
229     }
230 
231   } else {
232     if (eventType != kEventTypeCallback) {
233       sendFatalFailureToHost("Unexpected event type for num ", &mNextNum);
234     }
235     if (mNextNum == 11) {
236       // This was our last callback.  Everything is good.
237       sendSuccessToHost();
238     }
239   }
240 
241   mNextNum++;
242   sInMethod = false;
243 }
244 
245 }  // namespace general_test
246