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("completeCallback called while another nanoapp "
72                            "method is running.");
73   }
74   sInMethod = true;
75   if ((data == nullptr) || (data == kOddData)) {
76     sendFatalFailureToHost(
77         "completeCallback called with nullptr or odd data.");
78   }
79   uint32_t num = *(reinterpret_cast<uint32_t*>(data));
80   uint16_t expectedEventType = 0xFFFF;
81   uint8_t expectedCallbackIndex = 0xFF;
82   switch (num) {
83     case 0:
84       expectedEventType = kEventType0;
85       expectedCallbackIndex = 0;
86       break;
87     case 1:
88       expectedEventType = kEventType0;
89       expectedCallbackIndex = 1;
90       break;
91     case 2:
92       expectedEventType = kEventType1;
93       expectedCallbackIndex = 0;
94       break;
95     case 3:
96       expectedEventType = kEventType1;
97       expectedCallbackIndex = 1;
98       break;
99     default:
100       sendFatalFailureToHost("completeCallback given bad data.", &num);
101   }
102   if (expectedEventType != eventType) {
103     sendFatalFailureToHost("completeCallback bad/eventType mismatch.");
104   }
105   if (expectedCallbackIndex != kCallbackIndex) {
106     sendFatalFailureToHost("Incorrect callback function called.");
107   }
108   uint8_t mask = static_cast<uint8_t>(1 << num);
109   if ((sCallbacksInvoked & mask) != 0) {
110     sendFatalFailureToHost("Complete callback invoked multiple times for ",
111                            &num);
112   }
113   sCallbacksInvoked |= mask;
114 
115   if (!chreSendEvent(kEventTypeCallback, nullptr, nullptr,
116                      chreGetInstanceId())) {
117     sendFatalFailureToHost("Failed chreSendEvent in callback.");
118   }
119   sInMethod = false;
120 }
121 
completeCallback0(uint16_t eventType,void * data)122 void SendEventTest::completeCallback0(uint16_t eventType, void *data) {
123   completeCallback<0>(eventType, data);
124 }
125 
completeCallback1(uint16_t eventType,void * data)126 void SendEventTest::completeCallback1(uint16_t eventType, void *data) {
127   completeCallback<1>(eventType, data);
128 }
129 
SendEventTest()130 SendEventTest::SendEventTest()
131   : Test(CHRE_API_VERSION_1_0) , mNextNum(0) {
132 }
133 
setUp(uint32_t messageSize,const void *)134 void SendEventTest::setUp(uint32_t messageSize, const void * /* message */) {
135   sInMethod = true;
136   if (messageSize != 0) {
137     sendFatalFailureToHost(
138         "SendEvent message expects 0 additional bytes, got ",
139         &messageSize);
140   }
141 
142   const uint32_t id = chreGetInstanceId();
143   for (uint32_t i = 0; i < arrayLength(mData); i++) {
144     mData[i] = i;
145   }
146 
147   // num: 0
148   if (!chreSendEvent(kEventType0, &mData[0], completeCallback0, id)) {
149     sendFatalFailureToHost("Failed chreSendEvent num 0");
150   }
151 
152   // num: 1
153   if (!chreSendEvent(kEventType0, &mData[1], completeCallback1, id)) {
154     sendFatalFailureToHost("Failed chreSendEvent num 1");
155   }
156 
157   // num: 2
158   if (!chreSendEvent(kEventType1, &mData[2], completeCallback0, id)) {
159     sendFatalFailureToHost("Failed chreSendEvent num 2");
160   }
161 
162   // num: 3
163   if (!chreSendEvent(kEventType1, &mData[3], completeCallback1, id)) {
164     sendFatalFailureToHost("Failed chreSendEvent num 3");
165   }
166 
167   // num: 4
168   if (!chreSendEvent(kEventType0, &mData[4], nullptr, id)) {
169     sendFatalFailureToHost("Failed chreSendEvent num 4");
170   }
171 
172   // num: 5
173   if (!chreSendEvent(kEventType1, &mData[5], nullptr, id)) {
174     sendFatalFailureToHost("Failed chreSendEvent num 5");
175   }
176 
177   // num: 6
178   if (!chreSendEvent(kEventType0, nullptr, nullptr, id)) {
179     sendFatalFailureToHost("Failed chreSendEvent num 6");
180   }
181 
182   // num: 7
183   if (!chreSendEvent(kEventType1, kOddData, nullptr, id)) {
184     sendFatalFailureToHost("Failed chreSendEvent num 7");
185   }
186 
187   sInMethod = false;
188 }
189 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)190 void SendEventTest::handleEvent(uint32_t senderInstanceId,
191                                 uint16_t eventType, const void* eventData) {
192   if (sInMethod) {
193     sendFatalFailureToHost("handleEvent invoked while another nanoapp "
194                            "method is running");
195   }
196   sInMethod = true;
197   if (senderInstanceId != chreGetInstanceId()) {
198     sendFatalFailureToHost("handleEvent got event from unexpected sender:",
199                            &senderInstanceId);
200   }
201 
202   if (mNextNum < 8) {
203     void *expectedData;
204     if (mNextNum < 6) {
205       expectedData = &mData[mNextNum];
206     } else if (mNextNum == 6) {
207       expectedData = nullptr;
208     } else {
209       expectedData = kOddData;
210     }
211 
212     uint16_t expectedEventType = 0xFFFF;
213     switch (mNextNum) {
214       case 0:
215       case 1:
216       case 4:
217       case 6:
218         expectedEventType = kEventType0;
219         break;
220       case 2:
221       case 3:
222       case 5:
223       case 7:
224         expectedEventType = kEventType1;
225         break;
226     }
227 
228     if (expectedEventType != eventType) {
229       sendFatalFailureToHost("Incorrect event type sent for num ",
230                              &mNextNum);
231     }
232     if (expectedData != eventData) {
233       sendFatalFailureToHost("Incorrect data sent for num ", &mNextNum);
234     }
235 
236   } else {
237     if (eventType != kEventTypeCallback) {
238       sendFatalFailureToHost("Unexpected event type for num ", &mNextNum);
239     }
240     if (mNextNum == 11) {
241       // This was our last callback.  Everything is good.
242       sendSuccessToHost();
243     }
244   }
245 
246   mNextNum++;
247   sInMethod = false;
248 }
249 
250 }  // namespace general_test
251