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