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