• 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 <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