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