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