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