1 /*
2 * Copyright (C) 2020 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 "transport_test.h"
18
19 #include <gtest/gtest.h>
20
21 #include <stdbool.h>
22 #include <stddef.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <thread>
26
27 #include "chpp/app.h"
28 #include "chpp/common/discovery.h"
29 #include "chpp/common/gnss.h"
30 #include "chpp/common/gnss_types.h"
31 #include "chpp/common/standard_uuids.h"
32 #include "chpp/common/wifi.h"
33 #include "chpp/common/wifi_types.h"
34 #include "chpp/common/wwan.h"
35 #include "chpp/crc.h"
36 #include "chpp/macros.h"
37 #include "chpp/memory.h"
38 #include "chpp/platform/utils.h"
39 #include "chpp/services/discovery.h"
40 #include "chpp/services/loopback.h"
41 #include "chpp/transport.h"
42 #include "chre/pal/wwan.h"
43
44 namespace {
45
46 // Preamble as separate bytes for testing
47 constexpr uint8_t kChppPreamble0 = 0x68;
48 constexpr uint8_t kChppPreamble1 = 0x43;
49
50 // Max size of payload sent to chppRxDataCb (bytes)
51 constexpr size_t kMaxChunkSize = 20000;
52
53 constexpr size_t kMaxPacketSize = kMaxChunkSize + CHPP_PREAMBLE_LEN_BYTES +
54 sizeof(ChppTransportHeader) +
55 sizeof(ChppTransportFooter);
56
57 // Input sizes to test the entire range of sizes with a few tests
58 constexpr int kChunkSizes[] = {0, 1, 2, 3, 4, 21, 100, 1000, 10001, 20000};
59
60 // Number of services
61 constexpr int kServiceCount = 3;
62
63 /*
64 * Test suite for the CHPP Transport Layer
65 */
66 class TransportTests : public testing::TestWithParam<int> {
67 protected:
SetUp()68 void SetUp() override {
69 chppClearTotalAllocBytes();
70 memset(&mTransportContext.linkParams, 0,
71 sizeof(mTransportContext.linkParams));
72 mTransportContext.linkParams.linkEstablished = true;
73 mTransportContext.linkParams.isLinkActive = true;
74 chppTransportInit(&mTransportContext, &mAppContext);
75 chppAppInit(&mAppContext, &mTransportContext);
76
77 mTransportContext.resetState = CHPP_RESET_STATE_NONE;
78
79 // Make sure CHPP has a correct count of the number of registered services
80 // on this platform, (in this case, 1,) as registered in the function
81 // chppRegisterCommonServices().
82 ASSERT_EQ(mAppContext.registeredServiceCount, kServiceCount);
83 }
84
TearDown()85 void TearDown() override {
86 chppAppDeinit(&mAppContext);
87 chppTransportDeinit(&mTransportContext);
88
89 EXPECT_EQ(chppGetTotalAllocBytes(), 0);
90 }
91
92 ChppTransportState mTransportContext = {};
93 ChppAppState mAppContext = {};
94 uint8_t mBuf[kMaxPacketSize] = {};
95 };
96
97 /**
98 * Wait for chppTransportDoWork() to finish after it is notified by
99 * chppEnqueueTxPacket to run.
100 *
101 * TODO: (b/177616847) Improve test robustness / synchronization without adding
102 * overhead to CHPP
103 */
WaitForTransport(struct ChppTransportState * transportContext)104 void WaitForTransport(struct ChppTransportState *transportContext) {
105 // Wait for linkParams.notifier.signal to be triggered and processed
106 volatile uint32_t k = 1;
107 while (transportContext->linkParams.notifier.signal == 0 && k > 0) {
108 k++;
109 }
110 while (transportContext->linkParams.notifier.signal != 0 && k > 0) {
111 k++;
112 }
113 ASSERT_FALSE(k == 0);
114 while (k < UINT16_MAX) {
115 k++;
116 }
117 while (k > 0) {
118 k--;
119 }
120
121 // Should have reset loc and length for next packet / datagram
122 EXPECT_EQ(transportContext->rxStatus.locInDatagram, 0);
123 EXPECT_EQ(transportContext->rxDatagram.length, 0);
124 }
125
126 /**
127 * Validates a ChppTestResponse. Since the error field within the
128 * ChppAppHeader struct is optional (and not used for common services), this
129 * function returns the error field to be checked if desired, depending on the
130 * service.
131 *
132 * @param buf Buffer containing response.
133 * @param ackSeq Ack sequence to be verified.
134 * @param handle Handle number to be verified
135 * @param transactionID Transaction ID to be verified.
136 *
137 * @return The error field within the ChppAppHeader struct that is used by some
138 * but not all services.
139 */
validateChppTestResponse(void * buf,uint8_t ackSeq,uint8_t handle,uint8_t transactionID)140 uint8_t validateChppTestResponse(void *buf, uint8_t ackSeq, uint8_t handle,
141 uint8_t transactionID) {
142 struct ChppTestResponse *response = (ChppTestResponse *)buf;
143
144 // Check preamble
145 EXPECT_EQ(response->preamble0, kChppPreamble0);
146 EXPECT_EQ(response->preamble1, kChppPreamble1);
147
148 // Check response transport headers
149 EXPECT_EQ(response->transportHeader.packetCode, CHPP_TRANSPORT_ERROR_NONE);
150 EXPECT_EQ(response->transportHeader.ackSeq, ackSeq);
151
152 // Check response app headers
153 EXPECT_EQ(response->appHeader.handle, handle);
154 EXPECT_EQ(response->appHeader.type, CHPP_MESSAGE_TYPE_SERVICE_RESPONSE);
155 EXPECT_EQ(response->appHeader.transaction, transactionID);
156
157 // Return optional response error to be checked if desired
158 return response->appHeader.error;
159 }
160
161 /**
162 * Aborts a packet and validates state.
163 *
164 * @param transportcontext Maintains status for each transport layer instance.
165 */
endAndValidatePacket(struct ChppTransportState * transportContext)166 void endAndValidatePacket(struct ChppTransportState *transportContext) {
167 chppRxPacketCompleteCb(transportContext);
168 EXPECT_EQ(transportContext->rxStatus.state, CHPP_STATE_PREAMBLE);
169 EXPECT_EQ(transportContext->rxStatus.locInDatagram, 0);
170 EXPECT_EQ(transportContext->rxDatagram.length, 0);
171 }
172
173 /**
174 * Adds a preamble to a certain location in a buffer, and increases the location
175 * accordingly, to account for the length of the added preamble.
176 *
177 * @param buf Buffer.
178 * @param location Location to add the preamble, which its value will be
179 * increased accordingly.
180 */
addPreambleToBuf(uint8_t * buf,size_t * location)181 void addPreambleToBuf(uint8_t *buf, size_t *location) {
182 buf[(*location)++] = kChppPreamble0;
183 buf[(*location)++] = kChppPreamble1;
184 }
185
186 /**
187 * Adds a transport header (with default values) to a certain location in a
188 * buffer, and increases the location accordingly, to account for the length of
189 * the added transport header.
190 *
191 * @param buf Buffer.
192 * @param location Location to add the transport header, which its value will be
193 * increased accordingly.
194 *
195 * @return Pointer to the added transport header (e.g. to modify its fields).
196 */
addTransportHeaderToBuf(uint8_t * buf,size_t * location)197 ChppTransportHeader *addTransportHeaderToBuf(uint8_t *buf, size_t *location) {
198 size_t oldLoc = *location;
199
200 // Default values for initial, minimum size request packet
201 ChppTransportHeader transHeader = {};
202 transHeader.flags = CHPP_TRANSPORT_FLAG_FINISHED_DATAGRAM;
203 transHeader.packetCode = CHPP_TRANSPORT_ERROR_NONE;
204 transHeader.ackSeq = 1;
205 transHeader.seq = 0;
206 transHeader.length = sizeof(ChppAppHeader);
207 transHeader.reserved = 0;
208
209 memcpy(&buf[*location], &transHeader, sizeof(transHeader));
210 *location += sizeof(transHeader);
211
212 return (ChppTransportHeader *)&buf[oldLoc];
213 }
214
215 /**
216 * Adds an app header (with default values) to a certain location in a buffer,
217 * and increases the location accordingly, to account for the length of the
218 * added app header.
219 *
220 * @param buf Buffer.
221 * @param location Location to add the app header, which its value will be
222 * increased accordingly.
223 *
224 * @return Pointer to the added app header (e.g. to modify its fields).
225 */
addAppHeaderToBuf(uint8_t * buf,size_t * location)226 ChppAppHeader *addAppHeaderToBuf(uint8_t *buf, size_t *location) {
227 size_t oldLoc = *location;
228
229 // Default values - to be updated later as necessary
230 ChppAppHeader appHeader = {};
231 appHeader.handle = CHPP_HANDLE_NEGOTIATED_RANGE_START;
232 appHeader.type = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
233 appHeader.transaction = 0;
234 appHeader.error = CHPP_APP_ERROR_NONE;
235 appHeader.command = 0;
236
237 memcpy(&buf[*location], &appHeader, sizeof(appHeader));
238 *location += sizeof(appHeader);
239
240 return (ChppAppHeader *)&buf[oldLoc];
241 }
242
243 /**
244 * Adds a transport footer to a certain location in a buffer, and increases the
245 * location accordingly, to account for the length of the added preamble.
246 *
247 * @param buf Buffer.
248 * @param location Location to add the footer. The value of location will be
249 * increased accordingly.
250 *
251 */
addTransportFooterToBuf(uint8_t * buf,size_t * location)252 void addTransportFooterToBuf(uint8_t *buf, size_t *location) {
253 uint32_t *checksum = (uint32_t *)&buf[*location];
254
255 *checksum = chppCrc32(0, &buf[CHPP_PREAMBLE_LEN_BYTES],
256 *location - CHPP_PREAMBLE_LEN_BYTES);
257
258 *location += sizeof(ChppTransportFooter);
259 }
260
261 /**
262 * Opens a service and checks to make sure it was opened correctly.
263 *
264 * @param transportContext Transport layer context.
265 * @param buf Buffer.
266 * @param ackSeq Ack sequence of the packet to be sent out
267 * @param seq Sequence number of the packet to be sent out.
268 * @param handle Handle of the service to be opened.
269 * @param transactionID Transaction ID for the open request.
270 * @param command Open command.
271 */
openService(ChppTransportState * transportContext,uint8_t * buf,uint8_t ackSeq,uint8_t seq,uint8_t handle,uint8_t transactionID,uint16_t command)272 void openService(ChppTransportState *transportContext, uint8_t *buf,
273 uint8_t ackSeq, uint8_t seq, uint8_t handle,
274 uint8_t transactionID, uint16_t command) {
275 size_t len = 0;
276
277 addPreambleToBuf(buf, &len);
278
279 ChppTransportHeader *transHeader = addTransportHeaderToBuf(buf, &len);
280 transHeader->ackSeq = ackSeq;
281 transHeader->seq = seq;
282
283 ChppAppHeader *appHeader = addAppHeaderToBuf(buf, &len);
284 appHeader->handle = handle;
285 appHeader->transaction = transactionID;
286 appHeader->command = command;
287
288 addTransportFooterToBuf(buf, &len);
289
290 // Send header + payload (if any) + footer
291 EXPECT_TRUE(chppRxDataCb(transportContext, buf, len));
292
293 // Check for correct state
294 uint8_t nextSeq = transHeader->seq + 1;
295 EXPECT_EQ(transportContext->rxStatus.expectedSeq, nextSeq);
296 EXPECT_EQ(transportContext->rxStatus.state, CHPP_STATE_PREAMBLE);
297
298 // Wait for response
299 WaitForTransport(transportContext);
300
301 // Validate common response fields
302 EXPECT_EQ(validateChppTestResponse(transportContext->pendingTxPacket.payload,
303 nextSeq, handle, transactionID),
304 CHPP_APP_ERROR_NONE);
305
306 // Check response length
307 EXPECT_EQ(sizeof(ChppTestResponse), CHPP_PREAMBLE_LEN_BYTES +
308 sizeof(ChppTransportHeader) +
309 sizeof(ChppAppHeader));
310 EXPECT_EQ(transportContext->pendingTxPacket.length,
311 sizeof(ChppTestResponse) + sizeof(ChppTransportFooter));
312 }
313
314 /**
315 * Sends a command to a service and checks for errors.
316 *
317 * @param transportContext Transport layer context.
318 * @param buf Buffer.
319 * @param ackSeq Ack sequence of the packet to be sent out
320 * @param seq Sequence number of the packet to be sent out.
321 * @param handle Handle of the service to be opened.
322 * @param transactionID Transaction ID for the open request.
323 * @param command Command to be sent.
324 */
sendCommandToService(ChppTransportState * transportContext,uint8_t * buf,uint8_t ackSeq,uint8_t seq,uint8_t handle,uint8_t transactionID,uint16_t command)325 void sendCommandToService(ChppTransportState *transportContext, uint8_t *buf,
326 uint8_t ackSeq, uint8_t seq, uint8_t handle,
327 uint8_t transactionID, uint16_t command) {
328 size_t len = 0;
329
330 addPreambleToBuf(buf, &len);
331
332 ChppTransportHeader *transHeader = addTransportHeaderToBuf(buf, &len);
333 transHeader->ackSeq = ackSeq;
334 transHeader->seq = seq;
335
336 ChppAppHeader *appHeader = addAppHeaderToBuf(buf, &len);
337 appHeader->handle = handle;
338 appHeader->transaction = transactionID;
339 appHeader->command = command;
340
341 addTransportFooterToBuf(buf, &len);
342
343 // Send header + payload (if any) + footer
344 EXPECT_TRUE(chppRxDataCb(transportContext, buf, len));
345
346 // Check for correct state
347 uint8_t nextSeq = transHeader->seq + 1;
348 EXPECT_EQ(transportContext->rxStatus.expectedSeq, nextSeq);
349 EXPECT_EQ(transportContext->rxStatus.state, CHPP_STATE_PREAMBLE);
350
351 // Wait for response
352 WaitForTransport(transportContext);
353
354 // Validate common response fields
355 EXPECT_EQ(validateChppTestResponse(transportContext->pendingTxPacket.payload,
356 nextSeq, handle, transactionID),
357 CHPP_APP_ERROR_NONE);
358 }
359
360 /**
361 * A series of zeros shouldn't change state from CHPP_STATE_PREAMBLE
362 */
TEST_P(TransportTests,ZeroNoPreambleInput)363 TEST_P(TransportTests, ZeroNoPreambleInput) {
364 size_t len = static_cast<size_t>(GetParam());
365 if (len <= kMaxChunkSize) {
366 EXPECT_TRUE(chppRxDataCb(&mTransportContext, mBuf, len));
367 EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
368 }
369 }
370
371 /**
372 * A preamble after a series of zeros input should change state from
373 * CHPP_STATE_PREAMBLE to CHPP_STATE_HEADER
374 */
TEST_P(TransportTests,ZeroThenPreambleInput)375 TEST_P(TransportTests, ZeroThenPreambleInput) {
376 size_t len = static_cast<size_t>(GetParam());
377
378 if (len <= kMaxChunkSize) {
379 // Add preamble at the end of mBuf, as individual bytes instead of using
380 // chppAddPreamble(&mBuf[preambleLoc])
381 size_t preambleLoc = MAX(0, len - CHPP_PREAMBLE_LEN_BYTES);
382 mBuf[preambleLoc] = kChppPreamble0;
383 mBuf[preambleLoc + 1] = kChppPreamble1;
384
385 if (len >= CHPP_PREAMBLE_LEN_BYTES) {
386 EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, len));
387 EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_HEADER);
388 } else {
389 EXPECT_TRUE(chppRxDataCb(&mTransportContext, mBuf, len));
390 EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
391 }
392 }
393 }
394
395 // Disabled because flaky (fixed in U).
396 // /**
397 // * Rx Testing with various length payloads of zeros
398 // */
399 // TEST_P(TransportTests, RxPayloadOfZeros) {
400 // mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
401 // size_t len = static_cast<size_t>(GetParam());
402 // bool validLen = (len <= CHPP_TRANSPORT_RX_MTU_BYTES);
403
404 // mTransportContext.txStatus.hasPacketsToSend = true;
405 // std::thread t1(chppWorkThreadStart, &mTransportContext);
406 // WaitForTransport(&mTransportContext);
407
408 // if (len <= kMaxChunkSize) {
409 // size_t loc = 0;
410 // addPreambleToBuf(mBuf, &loc);
411 // ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
412
413 // transHeader->length = static_cast<uint16_t>(len);
414 // loc += len;
415
416 // addTransportFooterToBuf(mBuf, &loc);
417
418 // // Send header and check for correct state
419 // EXPECT_EQ(
420 // chppRxDataCb(&mTransportContext, mBuf,
421 // CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader)),
422 // !validLen);
423
424 // if (!validLen) {
425 // EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
426 // } else if (len > 0) {
427 // EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PAYLOAD);
428 // } else {
429 // EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_FOOTER);
430 // }
431
432 // // Correct decoding of packet length
433 // EXPECT_EQ(mTransportContext.rxHeader.length, len);
434 // EXPECT_EQ(mTransportContext.rxStatus.locInDatagram, 0);
435 // EXPECT_EQ(mTransportContext.rxDatagram.length, validLen ? len : 0);
436
437 // // Send payload if any and check for correct state
438 // if (len > 0) {
439 // EXPECT_EQ(
440 // chppRxDataCb(
441 // &mTransportContext,
442 // &mBuf[CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader)],
443 // len),
444 // !validLen);
445 // EXPECT_EQ(mTransportContext.rxStatus.state,
446 // validLen ? CHPP_STATE_FOOTER : CHPP_STATE_PREAMBLE);
447 // }
448
449 // // Should have complete packet payload by now
450 // EXPECT_EQ(mTransportContext.rxStatus.locInDatagram, validLen ? len : 0);
451
452 // // But no ACK yet
453 // EXPECT_EQ(mTransportContext.rxStatus.expectedSeq, transHeader->seq);
454
455 // // Send footer
456 // EXPECT_TRUE(chppRxDataCb(
457 // &mTransportContext,
458 // &mBuf[CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) + len],
459 // sizeof(ChppTransportFooter)));
460
461 // // The next expected packet sequence # should incremented only if the
462 // // received packet is payload-bearing.
463 // uint8_t nextSeq = transHeader->seq + ((validLen && len > 0) ? 1 : 0);
464 // EXPECT_EQ(mTransportContext.rxStatus.expectedSeq, nextSeq);
465
466 // // Check for correct ACK crafting if applicable (i.e. if the received
467 // packet
468 // // is payload-bearing).
469 // if (validLen && len > 0) {
470 // // TODO: Remove later as can cause flaky tests
471 // // These are expected to change shortly afterwards, as
472 // chppTransportDoWork
473 // // is run
474 // // EXPECT_TRUE(mTransportContext.txStatus.hasPacketsToSend);
475 // EXPECT_EQ(mTransportContext.txStatus.packetCodeToSend,
476 // CHPP_TRANSPORT_ERROR_NONE);
477 // EXPECT_EQ(mTransportContext.txDatagramQueue.pending, 0);
478
479 // WaitForTransport(&mTransportContext);
480
481 // // Check response packet fields
482 // struct ChppTransportHeader *txHeader =
483 // (struct ChppTransportHeader *)&mTransportContext.pendingTxPacket
484 // .payload[CHPP_PREAMBLE_LEN_BYTES];
485 // EXPECT_EQ(txHeader->flags, CHPP_TRANSPORT_FLAG_FINISHED_DATAGRAM);
486 // EXPECT_EQ(txHeader->packetCode, CHPP_TRANSPORT_ERROR_NONE);
487 // EXPECT_EQ(txHeader->ackSeq, nextSeq);
488 // EXPECT_EQ(txHeader->length, 0);
489
490 // // Check outgoing packet length
491 // EXPECT_EQ(mTransportContext.pendingTxPacket.length,
492 // CHPP_PREAMBLE_LEN_BYTES + sizeof(struct ChppTransportHeader)
493 // +
494 // sizeof(struct ChppTransportFooter));
495 // }
496
497 // // Check for correct state
498 // EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
499
500 // // Should have reset loc and length for next packet / datagram
501 // EXPECT_EQ(mTransportContext.rxStatus.locInDatagram, 0);
502 // EXPECT_EQ(mTransportContext.rxDatagram.length, 0);
503 // }
504
505 // chppWorkThreadStop(&mTransportContext);
506 // t1.join();
507 // }
508
509 /**
510 * End of Packet Link Notification during preamble
511 */
TEST_F(TransportTests,LinkSendDonePreamble)512 TEST_F(TransportTests, LinkSendDonePreamble) {
513 size_t payloadLen = 1000;
514 size_t partLenPreamble = CHPP_PREAMBLE_LEN_BYTES - 1;
515
516 mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
517 mTransportContext.txStatus.hasPacketsToSend = true;
518 std::thread t1(chppWorkThreadStart, &mTransportContext);
519 WaitForTransport(&mTransportContext);
520
521 size_t loc = 0;
522 addPreambleToBuf(mBuf, &loc);
523 ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
524 transHeader->length = static_cast<uint16_t>(payloadLen);
525 loc += payloadLen;
526 addTransportFooterToBuf(mBuf, &loc);
527
528 EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, partLenPreamble));
529 EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
530 endAndValidatePacket(&mTransportContext);
531
532 chppWorkThreadStop(&mTransportContext);
533 t1.join();
534 }
535
536 /**
537 * End of Packet Link Notification during header
538 */
TEST_F(TransportTests,LinkSendDoneHeader)539 TEST_F(TransportTests, LinkSendDoneHeader) {
540 size_t payloadLen = 1000;
541 size_t partLenHeader =
542 CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) - 1;
543
544 mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
545 mTransportContext.txStatus.hasPacketsToSend = true;
546 std::thread t1(chppWorkThreadStart, &mTransportContext);
547 WaitForTransport(&mTransportContext);
548
549 size_t loc = 0;
550 addPreambleToBuf(mBuf, &loc);
551 ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
552 transHeader->length = static_cast<uint16_t>(payloadLen);
553 loc += payloadLen;
554 addTransportFooterToBuf(mBuf, &loc);
555
556 EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, partLenHeader));
557 EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_HEADER);
558 EXPECT_EQ(mTransportContext.rxHeader.length, payloadLen);
559 endAndValidatePacket(&mTransportContext);
560
561 chppWorkThreadStop(&mTransportContext);
562 t1.join();
563 }
564
565 /**
566 * End of Packet Link Notification during payload
567 */
TEST_F(TransportTests,LinkSendDonePayload)568 TEST_F(TransportTests, LinkSendDonePayload) {
569 size_t payloadLen = 1000;
570 size_t partLenPayload = 500;
571
572 mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
573 mTransportContext.txStatus.hasPacketsToSend = true;
574 std::thread t1(chppWorkThreadStart, &mTransportContext);
575 WaitForTransport(&mTransportContext);
576
577 size_t loc = 0;
578 addPreambleToBuf(mBuf, &loc);
579 ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
580 transHeader->length = static_cast<uint16_t>(payloadLen);
581 loc += payloadLen;
582 addTransportFooterToBuf(mBuf, &loc);
583
584 EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, partLenPayload));
585 EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PAYLOAD);
586 EXPECT_EQ(mTransportContext.rxHeader.length, payloadLen);
587 EXPECT_EQ(
588 mTransportContext.rxStatus.locInDatagram,
589 partLenPayload - CHPP_PREAMBLE_LEN_BYTES - sizeof(ChppTransportHeader));
590 EXPECT_EQ(mTransportContext.rxDatagram.length, payloadLen);
591 endAndValidatePacket(&mTransportContext);
592
593 chppWorkThreadStop(&mTransportContext);
594 t1.join();
595 }
596
597 /**
598 * End of Packet Link Notification during footer
599 */
TEST_F(TransportTests,LinkSendDoneFooter)600 TEST_F(TransportTests, LinkSendDoneFooter) {
601 size_t payloadLen = 1000;
602 size_t partLenFooter = CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) +
603 payloadLen + sizeof(ChppTransportFooter) - 1;
604
605 mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
606 mTransportContext.txStatus.hasPacketsToSend = true;
607 std::thread t1(chppWorkThreadStart, &mTransportContext);
608 WaitForTransport(&mTransportContext);
609
610 size_t loc = 0;
611 addPreambleToBuf(mBuf, &loc);
612 ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
613 transHeader->length = static_cast<uint16_t>(payloadLen);
614 loc += payloadLen;
615 addTransportFooterToBuf(mBuf, &loc);
616
617 EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, partLenFooter));
618 EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_FOOTER);
619 EXPECT_EQ(mTransportContext.rxHeader.length, payloadLen);
620 EXPECT_EQ(mTransportContext.rxStatus.locInDatagram, payloadLen);
621 EXPECT_EQ(mTransportContext.rxDatagram.length, payloadLen);
622 endAndValidatePacket(&mTransportContext);
623
624 chppWorkThreadStop(&mTransportContext);
625 t1.join();
626 }
627
TEST_P(TransportTests,EnqueueDatagrams)628 TEST_P(TransportTests, EnqueueDatagrams) {
629 size_t len = static_cast<size_t>(GetParam());
630
631 if (len <= CHPP_TX_DATAGRAM_QUEUE_LEN) {
632 // Add (len) datagrams of various length to queue
633
634 int fr = 0;
635
636 for (int j = 0; j == CHPP_TX_DATAGRAM_QUEUE_LEN; j++) {
637 for (size_t i = 1; i <= len; i++) {
638 uint8_t *mBuf = (uint8_t *)chppMalloc(i + 100);
639 EXPECT_TRUE(
640 chppEnqueueTxDatagramOrFail(&mTransportContext, mBuf, i + 100));
641
642 EXPECT_EQ(mTransportContext.txDatagramQueue.pending, i);
643 EXPECT_EQ(mTransportContext.txDatagramQueue.front, fr);
644 EXPECT_EQ(mTransportContext.txDatagramQueue
645 .datagram[(i - 1 + fr) % CHPP_TX_DATAGRAM_QUEUE_LEN]
646 .length,
647 i + 100);
648 }
649
650 if (mTransportContext.txDatagramQueue.pending ==
651 CHPP_TX_DATAGRAM_QUEUE_LEN) {
652 uint8_t *mBuf = (uint8_t *)chppMalloc(100);
653 EXPECT_FALSE(
654 chppEnqueueTxDatagramOrFail(&mTransportContext, mBuf, 100));
655 CHPP_FREE_AND_NULLIFY(mBuf);
656 }
657
658 for (size_t i = len; i > 0; i--) {
659 fr++;
660 fr %= CHPP_TX_DATAGRAM_QUEUE_LEN;
661
662 EXPECT_TRUE(chppDequeueTxDatagram(&mTransportContext));
663
664 EXPECT_EQ(mTransportContext.txDatagramQueue.front, fr);
665 EXPECT_EQ(mTransportContext.txDatagramQueue.pending, i - 1);
666 }
667
668 EXPECT_FALSE(chppDequeueTxDatagram(&mTransportContext));
669
670 EXPECT_EQ(mTransportContext.txDatagramQueue.front, fr);
671 EXPECT_EQ(mTransportContext.txDatagramQueue.pending, 0);
672 }
673 }
674 }
675
676 /**
677 * Loopback testing with various length payloads of zeros
678 */
TEST_P(TransportTests,LoopbackPayloadOfZeros)679 TEST_P(TransportTests, LoopbackPayloadOfZeros) {
680 mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
681 size_t len = static_cast<size_t>(GetParam());
682
683 mTransportContext.txStatus.hasPacketsToSend = true;
684 std::thread t1(chppWorkThreadStart, &mTransportContext);
685 WaitForTransport(&mTransportContext);
686 chppWorkThreadStop(&mTransportContext);
687 t1.join();
688
689 if (len > 1 && len <= kMaxChunkSize) {
690 // Loopback App header (only 2 fields required)
691 mBuf[0] = CHPP_HANDLE_LOOPBACK;
692 mBuf[1] = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
693
694 EXPECT_TRUE(chppDispatchLoopbackClientRequest(&mAppContext, mBuf, len));
695
696 uint16_t end = (mTransportContext.txDatagramQueue.front +
697 mTransportContext.txDatagramQueue.pending - 1) %
698 CHPP_TX_DATAGRAM_QUEUE_LEN;
699
700 EXPECT_EQ(mTransportContext.txDatagramQueue.datagram[end].length, len);
701 EXPECT_EQ(mTransportContext.txDatagramQueue.datagram[end].payload[0],
702 CHPP_HANDLE_LOOPBACK);
703 EXPECT_EQ(mTransportContext.txDatagramQueue.datagram[end].payload[1],
704 CHPP_MESSAGE_TYPE_SERVICE_RESPONSE);
705 }
706 }
707
708 /**
709 * Discovery service + Transaction ID
710 */
TEST_P(TransportTests,DiscoveryAndTransactionID)711 TEST_P(TransportTests, DiscoveryAndTransactionID) {
712 uint8_t transactionID = static_cast<uint8_t>(GetParam());
713 size_t len = 0;
714
715 mTransportContext.txStatus.hasPacketsToSend = true;
716 std::thread t1(chppWorkThreadStart, &mTransportContext);
717 WaitForTransport(&mTransportContext);
718 chppWorkThreadStop(&mTransportContext);
719 t1.join();
720
721 ChppAppHeader *appHeader = addAppHeaderToBuf(mBuf, &len);
722 appHeader->handle = CHPP_HANDLE_DISCOVERY;
723 appHeader->transaction = transactionID;
724 appHeader->command = CHPP_DISCOVERY_COMMAND_DISCOVER_ALL;
725
726 EXPECT_TRUE(chppDispatchDiscoveryClientRequest(&mAppContext, mBuf, len));
727
728 uint16_t end = (mTransportContext.txDatagramQueue.front +
729 mTransportContext.txDatagramQueue.pending - 1) %
730 CHPP_TX_DATAGRAM_QUEUE_LEN;
731
732 struct ChppAppHeader *responseHeader =
733 (ChppAppHeader *)mTransportContext.txDatagramQueue.datagram[end].payload;
734
735 EXPECT_EQ(responseHeader->handle, CHPP_HANDLE_DISCOVERY);
736 EXPECT_EQ(responseHeader->type, CHPP_MESSAGE_TYPE_SERVICE_RESPONSE);
737 EXPECT_EQ(responseHeader->transaction, transactionID);
738 EXPECT_EQ(responseHeader->error, CHPP_APP_ERROR_NONE);
739 EXPECT_EQ(responseHeader->command, CHPP_DISCOVERY_COMMAND_DISCOVER_ALL);
740
741 // Decode discovery response
742 ChppServiceDescriptor *services =
743 (ChppServiceDescriptor *)&mTransportContext.txDatagramQueue.datagram[end]
744 .payload[sizeof(ChppAppHeader)];
745
746 // Check total length (and implicit service count)
747 EXPECT_EQ(
748 mTransportContext.txDatagramQueue.datagram[end].length,
749 sizeof(ChppAppHeader) + kServiceCount * sizeof(ChppServiceDescriptor));
750
751 // Check service configuration response
752 ChppServiceDescriptor wwanServiceDescriptor = {};
753 static const uint8_t uuid[CHPP_SERVICE_UUID_LEN] = CHPP_UUID_WWAN_STANDARD;
754 memcpy(&wwanServiceDescriptor.uuid, &uuid,
755 sizeof(wwanServiceDescriptor.uuid));
756 static const char name[CHPP_SERVICE_NAME_MAX_LEN] = "WWAN";
757 memcpy(&wwanServiceDescriptor.name, &name,
758 sizeof(wwanServiceDescriptor.name));
759 wwanServiceDescriptor.version.major = 1;
760 wwanServiceDescriptor.version.minor = 0;
761 wwanServiceDescriptor.version.patch = 0;
762
763 EXPECT_EQ(std::memcmp(services[0].uuid, wwanServiceDescriptor.uuid,
764 sizeof(wwanServiceDescriptor.uuid)),
765 0);
766 EXPECT_EQ(std::memcmp(services[0].name, wwanServiceDescriptor.name,
767 sizeof(wwanServiceDescriptor.name)),
768 0);
769 EXPECT_EQ(services[0].version.major, wwanServiceDescriptor.version.major);
770 EXPECT_EQ(services[0].version.minor, wwanServiceDescriptor.version.minor);
771 EXPECT_EQ(services[0].version.patch, wwanServiceDescriptor.version.patch);
772 }
773
774 /**
775 * CRC-32 calculation for several pre-known test vectors.
776 */
TEST_F(TransportTests,CRC32Basic)777 TEST_F(TransportTests, CRC32Basic) {
778 static const char kTest1Str[] = "Hello World Test!";
779 static const uint8_t *kTest1 = (const uint8_t *)kTest1Str;
780 EXPECT_EQ(chppCrc32(0, kTest1, 17), 0x613B1D74);
781 EXPECT_EQ(chppCrc32(0, kTest1, 16), 0x5F88D7D9);
782 EXPECT_EQ(chppCrc32(0, kTest1, 1), 0xAA05262F);
783 EXPECT_EQ(chppCrc32(0, kTest1, 0), 0x00000000);
784
785 static const uint8_t kTest2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
786 EXPECT_EQ(chppCrc32(0, kTest2, 6), 0x41D9ED00);
787 EXPECT_EQ(chppCrc32(0, kTest2, 5), 0xD2FD1072);
788 EXPECT_EQ(chppCrc32(0, kTest2, 4), 0xFFFFFFFF);
789 EXPECT_EQ(chppCrc32(0, kTest2, 3), 0xFFFFFF00);
790 EXPECT_EQ(chppCrc32(0, kTest2, 2), 0xFFFF0000);
791 EXPECT_EQ(chppCrc32(0, kTest2, 1), 0xFF000000);
792 EXPECT_EQ(chppCrc32(0, kTest2, 0), 0x00000000);
793
794 static const char kTest3Str[] = "123456789";
795 static const uint8_t *kTest3 = (const uint8_t *)kTest3Str;
796 EXPECT_EQ(chppCrc32(0, kTest3, 9), 0xCBF43926);
797
798 static const uint8_t kTest4[] = {0x00, 0x00, 0x00, 0x00};
799 EXPECT_EQ(chppCrc32(0, kTest4, sizeof(kTest4)), 0x2144DF1C);
800
801 static const uint8_t kTest5[] = {0xF2, 0x01, 0x83};
802 EXPECT_EQ(chppCrc32(0, kTest5, sizeof(kTest5)), 0x24AB9D77);
803
804 static const uint8_t kTest6[] = {0x0F, 0xAA, 0x00, 0x55};
805 EXPECT_EQ(chppCrc32(0, kTest6, sizeof(kTest6)), 0xB6C9B287);
806
807 static const uint8_t kTest7[] = {0x00, 0xFF, 0x55, 0x11};
808 EXPECT_EQ(chppCrc32(0, kTest7, sizeof(kTest7)), 0x32A06212);
809
810 static const uint8_t kTest8[] = {0x33, 0x22, 0x55, 0xAA, 0xBB,
811 0xCC, 0xDD, 0xEE, 0xFF};
812 EXPECT_EQ(chppCrc32(0, kTest8, sizeof(kTest8)), 0xB0AE863D);
813
814 static const uint8_t kTest9[] = {0x92, 0x6B, 0x55};
815 EXPECT_EQ(chppCrc32(0, kTest9, sizeof(kTest9)), 0x9CDEA29B);
816 }
817
818 /**
819 * CRC-32 calculation for daisy-chained input.
820 */
TEST_F(TransportTests,CRC32DaisyChained)821 TEST_F(TransportTests, CRC32DaisyChained) {
822 static const size_t kMaxLen = 10000;
823 uint8_t test[kMaxLen];
824 // Populate test with 8-bit LFSR
825 // Feedback polynomial is x^8 + x^6 + x^5 + x^4 + 1
826 static uint8_t lfsr = 1;
827 for (size_t i = 0; i < kMaxLen; i++) {
828 test[i] = lfsr;
829 lfsr = (lfsr >> 1) |
830 (((lfsr << 7) ^ (lfsr << 5) ^ (lfsr << 4) ^ (lfsr << 3)) & 0x80);
831 }
832
833 for (size_t len = 0; len < kMaxLen; len += 1000) {
834 uint32_t fullCRC = chppCrc32(0, &test[0], len);
835 for (size_t partition = 0; partition <= len; partition++) {
836 uint32_t partialCRC = chppCrc32(0, &test[0], partition);
837 EXPECT_EQ(chppCrc32(partialCRC, &test[partition], len - partition),
838 fullCRC);
839 }
840 }
841 }
842
843 /**
844 * WWAN service Open and GetCapabilities.
845 */
TEST_F(TransportTests,WwanOpen)846 TEST_F(TransportTests, WwanOpen) {
847 mTransportContext.txStatus.hasPacketsToSend = true;
848 std::thread t1(chppWorkThreadStart, &mTransportContext);
849 WaitForTransport(&mTransportContext);
850
851 uint8_t ackSeq = 1;
852 uint8_t seq = 0;
853 uint8_t handle = CHPP_HANDLE_NEGOTIATED_RANGE_START;
854 uint8_t transactionID = 0;
855 size_t len = 0;
856
857 openService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
858 transactionID++, CHPP_WWAN_OPEN);
859
860 addPreambleToBuf(mBuf, &len);
861
862 uint16_t command = CHPP_WWAN_GET_CAPABILITIES;
863 sendCommandToService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
864 transactionID++, command);
865
866 size_t responseLoc = sizeof(ChppTestResponse);
867
868 // Validate capabilities
869 uint32_t *capabilities =
870 (uint32_t *)&mTransportContext.pendingTxPacket.payload[responseLoc];
871 responseLoc += sizeof(uint32_t);
872
873 // Cleanup
874 chppWorkThreadStop(&mTransportContext);
875 t1.join();
876
877 uint32_t capabilitySet = CHRE_WWAN_GET_CELL_INFO;
878 EXPECT_EQ((*capabilities) & ~(capabilitySet), 0);
879
880 // Check total length
881 EXPECT_EQ(responseLoc, CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) +
882 sizeof(ChppWwanGetCapabilitiesResponse));
883 }
884
885 /**
886 * WiFi service Open and GetCapabilities.
887 */
TEST_F(TransportTests,WifiOpen)888 TEST_F(TransportTests, WifiOpen) {
889 mTransportContext.txStatus.hasPacketsToSend = true;
890 std::thread t1(chppWorkThreadStart, &mTransportContext);
891 WaitForTransport(&mTransportContext);
892
893 uint8_t ackSeq = 1;
894 uint8_t seq = 0;
895 uint8_t handle = CHPP_HANDLE_NEGOTIATED_RANGE_START + 1;
896 uint8_t transactionID = 0;
897
898 openService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
899 transactionID++, CHPP_WIFI_OPEN);
900
901 uint16_t command = CHPP_WIFI_GET_CAPABILITIES;
902 sendCommandToService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
903 transactionID++, command);
904
905 size_t responseLoc = sizeof(ChppTestResponse);
906
907 // Cleanup
908 chppWorkThreadStop(&mTransportContext);
909 t1.join();
910
911 // Validate capabilities
912 uint32_t *capabilities =
913 (uint32_t *)&mTransportContext.pendingTxPacket.payload[responseLoc];
914 responseLoc += sizeof(uint32_t);
915
916 uint32_t capabilitySet = CHRE_WIFI_CAPABILITIES_SCAN_MONITORING |
917 CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN |
918 CHRE_WIFI_CAPABILITIES_RADIO_CHAIN_PREF |
919 CHRE_WIFI_CAPABILITIES_RTT_RANGING |
920 CHRE_WIFI_CAPABILITIES_NAN_SUB;
921 EXPECT_EQ((*capabilities) & ~(capabilitySet), 0);
922
923 // Check total length
924 EXPECT_EQ(responseLoc, CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) +
925 sizeof(ChppWwanGetCapabilitiesResponse));
926 }
927
928 // Disabled because flaky (fixed in U).
929 // /**
930 // * GNSS service Open and GetCapabilities.
931 // */
932 // TEST_F(TransportTests, GnssOpen) {
933 // mTransportContext.txStatus.hasPacketsToSend = true;
934 // std::thread t1(chppWorkThreadStart, &mTransportContext);
935 // WaitForTransport(&mTransportContext);
936
937 // uint8_t ackSeq = 1;
938 // uint8_t seq = 0;
939 // uint8_t handle = CHPP_HANDLE_NEGOTIATED_RANGE_START + 2;
940 // uint8_t transactionID = 0;
941 // size_t len = 0;
942
943 // openService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
944 // transactionID++, CHPP_GNSS_OPEN);
945
946 // addPreambleToBuf(mBuf, &len);
947
948 // uint16_t command = CHPP_GNSS_GET_CAPABILITIES;
949 // sendCommandToService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
950 // transactionID++, command);
951
952 // size_t responseLoc = sizeof(ChppTestResponse);
953
954 // // Cleanup
955 // chppWorkThreadStop(&mTransportContext);
956 // t1.join();
957
958 // // Validate capabilities
959 // uint32_t *capabilities =
960 // (uint32_t *)&mTransportContext.pendingTxPacket.payload[responseLoc];
961 // responseLoc += sizeof(uint32_t);
962
963 // uint32_t capabilitySet =
964 // CHRE_GNSS_CAPABILITIES_LOCATION | CHRE_GNSS_CAPABILITIES_MEASUREMENTS |
965 // CHRE_GNSS_CAPABILITIES_GNSS_ENGINE_BASED_PASSIVE_LISTENER;
966 // EXPECT_EQ((*capabilities) & ~(capabilitySet), 0);
967
968 // // Check total length
969 // EXPECT_EQ(responseLoc, CHPP_PREAMBLE_LEN_BYTES +
970 // sizeof(ChppTransportHeader) +
971 // sizeof(ChppGnssGetCapabilitiesResponse));
972 // }
973
974 /**
975 * Discovery client.
976 */
TEST_F(TransportTests,Discovery)977 TEST_F(TransportTests, Discovery) {
978 size_t len = 0;
979
980 mTransportContext.txStatus.hasPacketsToSend = true;
981 std::thread t1(chppWorkThreadStart, &mTransportContext);
982 WaitForTransport(&mTransportContext);
983
984 addPreambleToBuf(mBuf, &len);
985
986 ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &len);
987
988 ChppAppHeader *appHeader = addAppHeaderToBuf(mBuf, &len);
989 appHeader->handle = CHPP_HANDLE_DISCOVERY;
990 appHeader->command = CHPP_DISCOVERY_COMMAND_DISCOVER_ALL;
991 appHeader->type = CHPP_MESSAGE_TYPE_SERVICE_RESPONSE;
992
993 ChppServiceDescriptor wwanServiceDescriptor = {};
994 static const uint8_t uuid[CHPP_SERVICE_UUID_LEN] = CHPP_UUID_WWAN_STANDARD;
995 memcpy(&wwanServiceDescriptor.uuid, &uuid,
996 sizeof(wwanServiceDescriptor.uuid));
997 static const char name[CHPP_SERVICE_NAME_MAX_LEN] = "WWAN";
998 memcpy(&wwanServiceDescriptor.name, &name,
999 sizeof(wwanServiceDescriptor.name));
1000 wwanServiceDescriptor.version.major = 1;
1001 wwanServiceDescriptor.version.minor = 0;
1002 wwanServiceDescriptor.version.patch = 0;
1003
1004 memcpy(&mBuf[len], &wwanServiceDescriptor, sizeof(ChppServiceDescriptor));
1005 len += sizeof(ChppServiceDescriptor);
1006
1007 transHeader->length = static_cast<uint16_t>(
1008 len - sizeof(ChppTransportHeader) - CHPP_PREAMBLE_LEN_BYTES);
1009
1010 addTransportFooterToBuf(mBuf, &len);
1011
1012 // Initialize clientIndexOfServiceIndex[0] to see if it correctly updated
1013 // upon discovery
1014 mAppContext.clientIndexOfServiceIndex[0] = CHPP_CLIENT_INDEX_NONE;
1015
1016 // Send header + payload (if any) + footer
1017 EXPECT_TRUE(chppRxDataCb(&mTransportContext, mBuf, len));
1018
1019 // Cleanup
1020 chppWorkThreadStop(&mTransportContext);
1021 t1.join();
1022
1023 // Check for correct state
1024 EXPECT_EQ(mAppContext.clientIndexOfServiceIndex[0], 0);
1025 uint8_t nextSeq = transHeader->seq + 1;
1026 EXPECT_EQ(mTransportContext.rxStatus.expectedSeq, nextSeq);
1027 EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
1028 }
1029
1030 /**
1031 * Unopened clients should not crash upon an unsolicitated service response.
1032 */
TEST_F(TransportTests,UnopenedClient)1033 TEST_F(TransportTests, UnopenedClient) {
1034 size_t len = 0;
1035 uint8_t *buf = (uint8_t *)chppMalloc(100);
1036
1037 mTransportContext.txStatus.hasPacketsToSend = true;
1038 std::thread t1(chppWorkThreadStart, &mTransportContext);
1039 WaitForTransport(&mTransportContext);
1040 chppWorkThreadStop(&mTransportContext);
1041 t1.join();
1042
1043 ChppAppHeader *appHeader = addAppHeaderToBuf(buf, &len);
1044 appHeader->handle = CHPP_HANDLE_NEGOTIATED_RANGE_START + 1;
1045 appHeader->command = CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC;
1046 appHeader->type = CHPP_MESSAGE_TYPE_SERVICE_RESPONSE;
1047 len = sizeof(struct ChppWifiConfigureScanMonitorAsyncResponse);
1048
1049 ASSERT_EQ(mAppContext.registeredServiceCount, kServiceCount);
1050
1051 chppAppProcessRxDatagram(&mAppContext, buf, len);
1052
1053 EXPECT_EQ(mTransportContext.txStatus.packetCodeToSend,
1054 CHPP_TRANSPORT_ERROR_APPLAYER);
1055 }
1056
TEST_F(TransportTests,DiscardedPacketTest)1057 TEST_F(TransportTests, DiscardedPacketTest) {
1058 mTransportContext.txStatus.hasPacketsToSend = true;
1059 std::thread t1(chppWorkThreadStart, &mTransportContext);
1060 WaitForTransport(&mTransportContext);
1061
1062 // Send packet to RX thread after manually setting to resetting state.
1063 // We expect this packet to get dropped, but this test checks for any
1064 // problematic behavior (e.g. memory leaks).
1065 mTransportContext.resetState = CHPP_RESET_STATE_RESETTING;
1066
1067 size_t loc = 0;
1068 addPreambleToBuf(mBuf, &loc);
1069 ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
1070
1071 ChppAppHeader *appHeader = addAppHeaderToBuf(mBuf, &loc);
1072 appHeader->handle = CHPP_HANDLE_DISCOVERY;
1073 appHeader->command = CHPP_DISCOVERY_COMMAND_DISCOVER_ALL;
1074 appHeader->type = CHPP_MESSAGE_TYPE_SERVICE_RESPONSE;
1075
1076 ChppServiceDescriptor wwanServiceDescriptor = {};
1077 static const uint8_t uuid[CHPP_SERVICE_UUID_LEN] = CHPP_UUID_WWAN_STANDARD;
1078 memcpy(&wwanServiceDescriptor.uuid, &uuid,
1079 sizeof(wwanServiceDescriptor.uuid));
1080 static const char name[CHPP_SERVICE_NAME_MAX_LEN] = "WWAN";
1081 memcpy(&wwanServiceDescriptor.name, &name,
1082 sizeof(wwanServiceDescriptor.name));
1083 wwanServiceDescriptor.version.major = 1;
1084 wwanServiceDescriptor.version.minor = 0;
1085 wwanServiceDescriptor.version.patch = 0;
1086
1087 memcpy(&mBuf[loc], &wwanServiceDescriptor, sizeof(ChppServiceDescriptor));
1088 loc += sizeof(ChppServiceDescriptor);
1089
1090 transHeader->length = static_cast<uint16_t>(
1091 loc - sizeof(ChppTransportHeader) - CHPP_PREAMBLE_LEN_BYTES);
1092
1093 addTransportFooterToBuf(mBuf, &loc);
1094
1095 mAppContext.clientIndexOfServiceIndex[0] = CHPP_CLIENT_INDEX_NONE;
1096
1097 EXPECT_TRUE(chppRxDataCb(&mTransportContext, mBuf, loc));
1098
1099 chppWorkThreadStop(&mTransportContext);
1100 t1.join();
1101 }
1102
1103 /*
1104 * Correctly handle messages directed to clients / services with an invalid
1105 * handle number.
1106 */
messageToInvalidHandle(ChppTransportState * transportContext,uint8_t type)1107 void messageToInvalidHandle(ChppTransportState *transportContext,
1108 uint8_t type) {
1109 size_t len = 0;
1110 uint8_t *buf = (uint8_t *)chppMalloc(100);
1111
1112 transportContext->txStatus.hasPacketsToSend = true;
1113 std::thread t1(chppWorkThreadStart, transportContext);
1114 WaitForTransport(transportContext);
1115 chppWorkThreadStop(transportContext);
1116 t1.join();
1117
1118 ChppAppHeader *appHeader = addAppHeaderToBuf(buf, &len);
1119 appHeader->handle =
1120 CHPP_HANDLE_NEGOTIATED_RANGE_START + CHPP_MAX_REGISTERED_CLIENTS;
1121 appHeader->type = type;
1122 len = sizeof(struct ChppAppHeader);
1123
1124 chppAppProcessRxDatagram(transportContext->appContext, buf, len);
1125
1126 EXPECT_EQ(transportContext->txStatus.packetCodeToSend,
1127 CHPP_TRANSPORT_ERROR_APPLAYER);
1128 }
1129
TEST_F(TransportTests,RequestToInvalidService)1130 TEST_F(TransportTests, RequestToInvalidService) {
1131 messageToInvalidHandle(&mTransportContext, CHPP_MESSAGE_TYPE_CLIENT_REQUEST);
1132 }
1133
TEST_F(TransportTests,ResponseToInvalidClient)1134 TEST_F(TransportTests, ResponseToInvalidClient) {
1135 messageToInvalidHandle(&mTransportContext,
1136 CHPP_MESSAGE_TYPE_SERVICE_RESPONSE);
1137 }
1138
TEST_F(TransportTests,NotificationToInvalidService)1139 TEST_F(TransportTests, NotificationToInvalidService) {
1140 messageToInvalidHandle(&mTransportContext,
1141 CHPP_MESSAGE_TYPE_CLIENT_NOTIFICATION);
1142 }
1143
TEST_F(TransportTests,NotificationToInvalidClient)1144 TEST_F(TransportTests, NotificationToInvalidClient) {
1145 messageToInvalidHandle(&mTransportContext,
1146 CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION);
1147 }
1148
1149 // Disabled because flaky (fixed in U).
1150 // TEST_F(TransportTests, WorkMonitorInvoked) {
1151 // // Send message to spin work thread so it interacts with the work monitor
1152 // messageToInvalidHandle(&mTransportContext,
1153 // CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION);
1154
1155 // // 1 pre/post call for executing the work and 1 for shutting down the
1156 // thread. EXPECT_EQ(mTransportContext.workMonitor.numPreProcessCalls, 2);
1157 // EXPECT_EQ(mTransportContext.workMonitor.numPostProcessCalls, 2);
1158 // }
1159
1160 INSTANTIATE_TEST_SUITE_P(TransportTestRange, TransportTests,
1161 testing::ValuesIn(kChunkSizes));
1162 } // namespace
1163