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