• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_message_to_host_test.h>
18 
19 #include <cinttypes>
20 #include <cstddef>
21 
22 #include <shared/nano_endian.h>
23 #include <shared/nano_string.h>
24 #include <shared/send_message.h>
25 
26 #include <chre.h>
27 
28 using nanoapp_testing::MessageType;
29 using nanoapp_testing::sendFatalFailureToHost;
30 using nanoapp_testing::sendInternalFailureToHost;
31 using nanoapp_testing::sendSuccessToHost;
32 
33 
34 /*
35  * Our test essentially has nine stages.  The first eight stages all involve
36  * sending data to the Host.  Here is a table describing them:
37  *
38  * Stage | Data length | Callback
39  * ------|-------------|--------------
40  * 0     | small       | smallMessage0
41  * 1     | small       | smallMessage1
42  * 2     | small       | nullptr
43  * 3     | small       | smallMessage0
44  * 4     | nullptr     | nullptr
45  * 5     | 4 bytes     | nullptr
46  * 6     | MAX + 1     | largeMessage
47  * 7     | MAX         | largeMessage
48  *
49  * Stage 8 involves waiting for an incoming zero-sized message from the Host.
50  *
51  * The focus of the first four stages is making sure the correct callback
52  * gets invoked and a nullptr callback works.
53  *
54  * Stage 4 tests sending a null message to the Host (that should send).
55  *
56  * Stage 5 is not testing anything, but it's necessary to get data
57  * to the host to confirm the message in stage 7 is correct.
58  *
59  * Stage 6 tests that we properly reject oversized messages.  This
60  * data should _not_ make it to the host.
61  *
62  * Stage 7 tests that we can send the maximum claimed size to the host.
63  *
64  * Every single stage which has a non-null callback is not considered a
65  * "success" until that callback has been invoked.  There is no CHRE
66  * requirement in terms of the order in which these callbacks are
67  * invoked, which is why the markSuccess() method uses a bitmask and
68  * checks for overall success every time we gets success from a single
69  * stage.
70  *
71  * We consider the test successful only when all stages have reported success.
72  * Note that the Host will not perform Stage 8 until after it has received
73  * all the expected messages from the nanoapp.  That's how we can confirm
74  * all messages actually made it through to the Host.
75  */
76 
77 // TODO(b/32114261): Remove this and actually test a variety of message types.
78 constexpr uint32_t kUntestedMessageType = UINT32_C(0x51501984);
79 
80 namespace general_test {
81 
82 // TODO(b/32114261): Remove this variable.
83 extern bool gUseNycMessageHack;
84 
85 uint8_t SendMessageToHostTest::sSmallMessageData[kSmallMessageTestCount][kSmallMessageSize];
86 void *SendMessageToHostTest::sLargeMessageData[2];
87 constexpr uint32_t SendMessageToHostTest::kLargeSizes[2];
88 
89 bool SendMessageToHostTest::sInMethod = false;
90 uint32_t SendMessageToHostTest::sFinishedBitmask = 0;
91 
92 template<uint8_t kCallbackIndex>
smallMessageCallback(void * message,size_t messageSize)93 void SendMessageToHostTest::smallMessageCallback(void *message,
94                                                  size_t messageSize) {
95   if (sInMethod) {
96     sendFatalFailureToHost("smallMessageCallback called while another "
97                            "nanoapp method is running");
98   }
99   sInMethod = true;
100   if (message == nullptr) {
101     sendFatalFailureToHost("smallMessageCallback given null message");
102   }
103   if (messageSize != kSmallMessageSize) {
104     uint32_t size = static_cast<uint32_t>(messageSize);
105     sendFatalFailureToHost("smallMessageCallback given bad messageSize:",
106                            &size);
107   }
108   const uint8_t *msg = static_cast<const uint8_t*>(message);
109   for (size_t i = 0; i < messageSize; i++) {
110     if (msg[i] != kDataByte) {
111       sendFatalFailureToHost("Corrupt data in smallMessageCallback");
112     }
113   }
114 
115   uint32_t stage = getSmallDataIndex(msg);
116   uint8_t expectedCallbackIndex = 2;
117   switch (stage) {
118     case 0:  // fall-through
119     case 3:
120       expectedCallbackIndex = 0;
121       break;
122     case 1:
123       expectedCallbackIndex = 1;
124       break;
125     case 2:
126       sendFatalFailureToHost("callback invoked when null callback "
127                              "given");
128       break;
129     default:
130       sendInternalFailureToHost("Invalid index", &stage);
131   }
132   if (expectedCallbackIndex != kCallbackIndex) {
133     sendFatalFailureToHost("Incorrect callback function called.");
134   }
135 
136   markSuccess(stage);
137   sInMethod = false;
138 }
139 
smallMessageCallback0(void * message,size_t messageSize)140 void SendMessageToHostTest::smallMessageCallback0(void *message,
141                                                   size_t messageSize) {
142   smallMessageCallback<0>(message, messageSize);
143 }
144 
smallMessageCallback1(void * message,size_t messageSize)145 void SendMessageToHostTest::smallMessageCallback1(void *message,
146                                                   size_t messageSize) {
147   smallMessageCallback<1>(message, messageSize);
148 }
149 
getSmallDataIndex(const uint8_t * data)150 uint32_t SendMessageToHostTest::getSmallDataIndex(const uint8_t *data) {
151   // O(N) is fine.  N is small and this is test code.
152   for (uint32_t i = 0; i < kSmallMessageTestCount; i++) {
153     if (data == sSmallMessageData[i]) {
154       return i;
155     }
156   }
157   sendFatalFailureToHost("Bad memory sent to smallMessageCallback");
158   // We should never get here.
159   return kSmallMessageTestCount;
160 }
161 
largeMessageCallback(void * message,size_t messageSize)162 void SendMessageToHostTest::largeMessageCallback(void *message,
163                                                  size_t messageSize) {
164   if (sInMethod) {
165     sendFatalFailureToHost("largeMessageCallback called while another "
166                            "nanoapp method is running");
167   }
168   sInMethod = true;
169   if (message == nullptr) {
170     sendFatalFailureToHost("largeMessageCallback given null message");
171   }
172   uint32_t index = 2;
173   if (message == sLargeMessageData[0]) {
174     index = 0;
175   } else if (message == sLargeMessageData[1]) {
176     index = 1;
177   } else {
178     sendFatalFailureToHost("largeMessageCallback given bad message");
179   }
180   if (messageSize != kLargeSizes[index]) {
181     sendFatalFailureToHost("largeMessageCallback given incorrect "
182                            "messageSize");
183   }
184   const uint8_t *msg = static_cast<const uint8_t*>(message);
185   for (size_t i = 0; i < messageSize; i++) {
186     if (msg[i] != kDataByte) {
187       sendFatalFailureToHost("Corrupt data in largeMessageCallback");
188     }
189   }
190   chreHeapFree(sLargeMessageData[index]);
191   // index 0 == stage 6, index 1 == stage 7
192   markSuccess(index + 6);
193 
194   sInMethod = false;
195 }
196 
markSuccess(uint32_t stage)197 void SendMessageToHostTest::markSuccess(uint32_t stage) {
198   chreLog(CHRE_LOG_DEBUG, "Stage %" PRIu32 " succeeded", stage);
199   uint32_t finishedBit = (1 << stage);
200   if (sFinishedBitmask & finishedBit) {
201     sendFatalFailureToHost("callback called multiple times for stage:",
202                            &stage);
203   }
204   if ((kAllFinished & finishedBit) == 0) {
205     sendFatalFailureToHost("markSuccess bad stage", &stage);
206   }
207   sFinishedBitmask |= finishedBit;
208   if (sFinishedBitmask == kAllFinished) {
209     sendSuccessToHost();
210   }
211 }
212 
prepTestMemory()213 void SendMessageToHostTest::prepTestMemory() {
214   nanoapp_testing::memset(sSmallMessageData, kDataByte,
215                           sizeof(sSmallMessageData));
216 
217   for (size_t i = 0; i < 2; i++) {
218     sLargeMessageData[i] = chreHeapAlloc(kLargeSizes[i]);
219     if (sLargeMessageData[i] == nullptr) {
220       sendFatalFailureToHost("Insufficient heap memory for test");
221     }
222     nanoapp_testing::memset(sLargeMessageData[i], kDataByte,
223                             kLargeSizes[i]);
224   }
225 }
226 
sendMessageMaxSize()227 void SendMessageToHostTest::sendMessageMaxSize() {
228   // Our focus here is just sending this data; we're not trying to
229   // test anything.  So we use the helper function.
230   uint32_t maxSize = nanoapp_testing::hostToLittleEndian(
231       static_cast<uint32_t>(CHRE_MESSAGE_TO_HOST_MAX_SIZE));
232   // TODO(b/32114261): We intentionally don't have a namespace using
233   //     declaration for sendMessageToHost because it's generally
234   //     incorrect to use while we're working around this bug.  When the
235   //     bug is fixed, we'll add this declaration, and use the method
236   //     widely.
237   nanoapp_testing::sendMessageToHost(MessageType::kContinue,
238                                      &maxSize, sizeof(maxSize));
239 }
240 
241 // Wrapper for chreSendMessageToHost() that sets sInMethod to false during its
242 // execution, to allow for inline callbacks (this CHRE API is allowed to call
243 // the free callback either within the function, or at an unspecified later time
244 // when this nanoapp is not otherwise executing).
sendMessageToHost(void * message,uint32_t messageSize,uint32_t reservedMessageType,chreMessageFreeFunction * freeCallback)245 bool SendMessageToHostTest::sendMessageToHost(
246     void *message, uint32_t messageSize, uint32_t reservedMessageType,
247     chreMessageFreeFunction *freeCallback) {
248   sInMethod = false;
249   bool success = chreSendMessageToHost(message, messageSize,
250                                        reservedMessageType, freeCallback);
251   sInMethod = true;
252 
253   return success;
254 }
255 
SendMessageToHostTest()256 SendMessageToHostTest::SendMessageToHostTest()
257   : Test(CHRE_API_VERSION_1_0) {
258 }
259 
setUp(uint32_t messageSize,const void *)260 void SendMessageToHostTest::setUp(uint32_t messageSize,
261                                   const void * /* message */) {
262   // TODO(b/32114261): We need this hackery so we can get the raw bytes
263   //     from the host, without the test infrastructure trying to
264   //     interpret them.  This won't be necessary when messageType is
265   //     properly sent.
266   gUseNycMessageHack = false;
267 
268   sInMethod = true;
269   if (messageSize != 0) {
270     sendFatalFailureToHost(
271         "SendMessageToHost message expects 0 additional bytes, got ",
272         &messageSize);
273   }
274 
275   prepTestMemory();
276 
277   // stage: 0
278   if (!sendMessageToHost(sSmallMessageData[0], kSmallMessageSize,
279                          kUntestedMessageType, smallMessageCallback0)) {
280     sendFatalFailureToHost("Failed chreSendMessageToHost stage 0");
281   }
282 
283   // stage: 1
284   if (!sendMessageToHost(sSmallMessageData[1], kSmallMessageSize,
285                          kUntestedMessageType, smallMessageCallback1)) {
286     sendFatalFailureToHost("Failed chreSendMessageToHost stage 1");
287   }
288 
289   // stage: 2
290   if (!sendMessageToHost(sSmallMessageData[2], kSmallMessageSize,
291                          kUntestedMessageType, nullptr)) {
292     sendFatalFailureToHost("Failed chreSendMessageToHost stage 2");
293   }
294   // There's no callback, so we mark this as a success.
295   markSuccess(2);
296 
297   // stage: 3
298   if (!sendMessageToHost(sSmallMessageData[3], kSmallMessageSize,
299                          kUntestedMessageType, smallMessageCallback0)) {
300     sendFatalFailureToHost("Failed chreSendMessageToHost stage 3");
301   }
302 
303   // stage: 4
304   if (!sendMessageToHost(nullptr, 0, kUntestedMessageType, nullptr)) {
305     sendFatalFailureToHost("Failed chreSendMessageToHost stage 4");
306   }
307   // There's no callback, so we mark this as a success.
308   markSuccess(4);
309 
310   // stage: 5
311   sendMessageMaxSize();
312   // There's no callback, so we mark this as a success.
313   markSuccess(5);
314 
315   // stage: 6
316   if (sendMessageToHost(sLargeMessageData[0], kLargeSizes[0],
317                         kUntestedMessageType, largeMessageCallback)) {
318     sendFatalFailureToHost("Oversized data to chreSendMessageToHost "
319                            "claimed success");
320   }
321 
322   // stage: 7
323   if (!sendMessageToHost(sLargeMessageData[1], kLargeSizes[1],
324                          kUntestedMessageType, largeMessageCallback)) {
325     sendFatalFailureToHost("Failed chreSendMessageToHost stage 7");
326   }
327 
328   sInMethod = false;
329 }
330 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)331 void SendMessageToHostTest::handleEvent(uint32_t senderInstanceId,
332                                         uint16_t eventType,
333                                         const void* eventData) {
334   if (sInMethod) {
335     sendFatalFailureToHost("handleEvent invoked while another nanoapp "
336                            "method is running");
337   }
338   sInMethod = true;
339 
340   // TODO(b/32114261): Use getMessageDataFromHostEvent().  We can't do
341   //     that now because our messageType is probably wrong.
342   if (senderInstanceId != CHRE_INSTANCE_ID) {
343     sendFatalFailureToHost("handleEvent got event from unexpected sender:",
344                            &senderInstanceId);
345   }
346   if (eventType != CHRE_EVENT_MESSAGE_FROM_HOST) {
347     unexpectedEvent(eventType);
348   }
349 
350   auto dataStruct = static_cast<const chreMessageFromHostData *>(eventData);
351   // TODO(b/32114261): Test the message type.
352   if (dataStruct->messageSize != 0) {
353     sendFatalFailureToHost("handleEvent got non-zero message size",
354                            &dataStruct->messageSize);
355   }
356   // We don't test dataStruct->message.  We don't require this to be
357   // nullptr.  If a CHRE choses to deal in 0-sized memory blocks, that's
358   // acceptable.
359 
360   // Stage 8 was successful.  Note that other stages might still be waiting
361   // for freeCallbacks.  So we don't send success to the host, but just
362   // mark our stage as a success.
363   markSuccess(8);
364 
365   sInMethod = false;
366 }
367 
368 }  // namespace general_test
369