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
27using nanoapp_testing::sendFatalFailureToHost;
28using 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
55constexpr uint16_t kEventType0 = CHRE_EVENT_FIRST_USER_VALUE + 0;
56constexpr uint16_t kEventType1 = CHRE_EVENT_FIRST_USER_VALUE + 1;
57constexpr 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.
61static void *kOddData = reinterpret_cast<void*>(-1);
62
63namespace general_test {
64
65bool SendEventTest::sInMethod = false;
66uint8_t SendEventTest::sCallbacksInvoked = 0;
67
68template<uint8_t kCallbackIndex>
69void 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 = 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
122void SendEventTest::completeCallback0(uint16_t eventType, void *data) {
123  completeCallback<0>(eventType, data);
124}
125
126void SendEventTest::completeCallback1(uint16_t eventType, void *data) {
127  completeCallback<1>(eventType, data);
128}
129
130SendEventTest::SendEventTest()
131  : Test(CHRE_API_VERSION_1_0) , mNextNum(0) {
132}
133
134void 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
190void 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