• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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