xref: /aosp_15_r20/system/chre/chpp/test/transport_test.cpp (revision 84e339476a462649f82315436d70fd732297a399)
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 chpp::test {
47 
48 namespace {
49 
50 // Max size of payload sent to chppRxDataCb (bytes)
51 constexpr size_t kMaxChunkSize = 20000;
52 
53 constexpr size_t kMaxPacketSize =
54     kMaxChunkSize + CHPP_TRANSPORT_ENCODING_OVERHEAD_BYTES;
55 
56 // Input sizes to test the entire range of sizes with a few tests
57 constexpr int kChunkSizes[] = {0, 1, 2, 3, 4, 21, 100, 1000, 10001, 20000};
58 
59 // Number of services
60 constexpr int kServiceCount = CHPP_EXPECTED_SERVICE_COUNT;
61 
62 // State of the link layer.
63 struct ChppLinuxLinkState gChppLinuxLinkContext;
64 
65 }  // namespace
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 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  * A series of zeros shouldn't change state from CHPP_STATE_PREAMBLE
105  */
TEST_P(TransportTests,ZeroNoPreambleInput)106 TEST_P(TransportTests, ZeroNoPreambleInput) {
107   size_t len = static_cast<size_t>(GetParam());
108   if (len <= kMaxChunkSize) {
109     EXPECT_TRUE(chppRxDataCb(&mTransportContext, mBuf, len));
110     EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
111   }
112 }
113 
114 /**
115  * A preamble after a series of zeros input should change state from
116  * CHPP_STATE_PREAMBLE to CHPP_STATE_HEADER
117  */
TEST_P(TransportTests,ZeroThenPreambleInput)118 TEST_P(TransportTests, ZeroThenPreambleInput) {
119   size_t len = static_cast<size_t>(GetParam());
120 
121   if (len <= kMaxChunkSize) {
122     // Add preamble at the end of mBuf, as individual bytes instead of using
123     // chppAddPreamble(&mBuf[preambleLoc])
124     size_t preambleLoc = MAX(0, len - CHPP_PREAMBLE_LEN_BYTES);
125     mBuf[preambleLoc] = kChppPreamble0;
126     mBuf[preambleLoc + 1] = kChppPreamble1;
127 
128     if (len >= CHPP_PREAMBLE_LEN_BYTES) {
129       EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, len));
130       EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_HEADER);
131     } else {
132       EXPECT_TRUE(chppRxDataCb(&mTransportContext, mBuf, len));
133       EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
134     }
135   }
136 }
137 
138 /**
139  * Rx Testing with various length payloads of zeros
140  */
TEST_P(TransportTests,RxPayloadOfZeros)141 TEST_P(TransportTests, RxPayloadOfZeros) {
142   mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
143   size_t len = static_cast<size_t>(GetParam());
144   bool isLenValid = (len <= chppTransportRxMtuSize(&mTransportContext));
145 
146   mTransportContext.txStatus.hasPacketsToSend = true;
147   std::thread t1(chppWorkThreadStart, &mTransportContext);
148   WaitForTransport(&mTransportContext);
149 
150   if (len <= kMaxChunkSize) {
151     size_t loc = 0;
152     addPreambleToBuf(mBuf, &loc);
153     ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
154 
155     transHeader->length = static_cast<uint16_t>(len);
156     loc += len;
157 
158     addTransportFooterToBuf(mBuf, &loc);
159 
160     // Send header and check for correct state
161     EXPECT_EQ(
162         chppRxDataCb(&mTransportContext, mBuf,
163                      CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader)),
164         !isLenValid);
165 
166     if (!isLenValid) {
167       EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
168     } else if (len > 0) {
169       EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PAYLOAD);
170     } else {
171       EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_FOOTER);
172     }
173 
174     // Correct decoding of packet length
175     EXPECT_EQ(mTransportContext.rxHeader.length, len);
176     EXPECT_EQ(mTransportContext.rxStatus.locInDatagram, 0);
177     EXPECT_EQ(mTransportContext.rxDatagram.length, isLenValid ? len : 0);
178 
179     // Send payload if any and check for correct state
180     if (len > 0) {
181       EXPECT_EQ(
182           chppRxDataCb(
183               &mTransportContext,
184               &mBuf[CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader)],
185               len),
186           !isLenValid);
187       EXPECT_EQ(mTransportContext.rxStatus.state,
188                 isLenValid ? CHPP_STATE_FOOTER : CHPP_STATE_PREAMBLE);
189     }
190 
191     // Should have complete packet payload by now
192     EXPECT_EQ(mTransportContext.rxStatus.locInDatagram, isLenValid ? len : 0);
193 
194     // But no ACK yet
195     EXPECT_EQ(mTransportContext.rxStatus.expectedSeq, transHeader->seq);
196 
197     // Send footer
198     EXPECT_TRUE(chppRxDataCb(
199         &mTransportContext,
200         &mBuf[CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) + len],
201         sizeof(ChppTransportFooter)));
202 
203     // The next expected packet sequence # should incremented only if the
204     // received packet is payload-bearing.
205     uint8_t nextSeq = transHeader->seq + ((isLenValid && len > 0) ? 1 : 0);
206     EXPECT_EQ(mTransportContext.rxStatus.expectedSeq, nextSeq);
207 
208     // Check for correct ACK crafting if applicable (i.e. if the received packet
209     // is payload-bearing).
210     if (isLenValid && len > 0) {
211       EXPECT_EQ(mTransportContext.txStatus.packetCodeToSend,
212                 CHPP_TRANSPORT_ERROR_NONE);
213       EXPECT_EQ(mTransportContext.txDatagramQueue.pending, 0);
214 
215       WaitForTransport(&mTransportContext);
216 
217       // Check response packet fields
218       struct ChppTransportHeader *txHeader =
219           (struct ChppTransportHeader *)&gChppLinuxLinkContext
220               .buf[CHPP_PREAMBLE_LEN_BYTES];
221       EXPECT_EQ(txHeader->flags, CHPP_TRANSPORT_FLAG_FINISHED_DATAGRAM);
222       EXPECT_EQ(txHeader->packetCode, CHPP_TRANSPORT_ERROR_NONE);
223       EXPECT_EQ(txHeader->ackSeq, nextSeq);
224       EXPECT_EQ(txHeader->length, 0);
225 
226       // Check outgoing packet length
227       EXPECT_EQ(mTransportContext.linkBufferSize,
228                 CHPP_PREAMBLE_LEN_BYTES + sizeof(struct ChppTransportHeader) +
229                     sizeof(struct ChppTransportFooter));
230     }
231 
232     // Check for correct state
233     EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
234 
235     // Should have reset loc and length for next packet / datagram
236     EXPECT_EQ(mTransportContext.rxStatus.locInDatagram, 0);
237     EXPECT_EQ(mTransportContext.rxDatagram.length, 0);
238   }
239 
240   chppWorkThreadStop(&mTransportContext);
241   t1.join();
242 }
243 
244 /**
245  * End of Packet Link Notification during preamble
246  */
TEST_F(TransportTests,LinkSendDonePreamble)247 TEST_F(TransportTests, LinkSendDonePreamble) {
248   size_t payloadLen = 1000;
249   size_t partLenPreamble = CHPP_PREAMBLE_LEN_BYTES - 1;
250 
251   mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
252   mTransportContext.txStatus.hasPacketsToSend = true;
253   std::thread t1(chppWorkThreadStart, &mTransportContext);
254   WaitForTransport(&mTransportContext);
255 
256   size_t loc = 0;
257   addPreambleToBuf(mBuf, &loc);
258   ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
259   transHeader->length = static_cast<uint16_t>(payloadLen);
260   loc += payloadLen;
261   addTransportFooterToBuf(mBuf, &loc);
262 
263   EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, partLenPreamble));
264   EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
265   endAndValidatePacket(&mTransportContext);
266 
267   chppWorkThreadStop(&mTransportContext);
268   t1.join();
269 }
270 
271 /**
272  * End of Packet Link Notification during header
273  */
TEST_F(TransportTests,LinkSendDoneHeader)274 TEST_F(TransportTests, LinkSendDoneHeader) {
275   size_t payloadLen = 1000;
276   size_t partLenHeader =
277       CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) - 1;
278 
279   mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
280   mTransportContext.txStatus.hasPacketsToSend = true;
281   std::thread t1(chppWorkThreadStart, &mTransportContext);
282   WaitForTransport(&mTransportContext);
283 
284   size_t loc = 0;
285   addPreambleToBuf(mBuf, &loc);
286   ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
287   transHeader->length = static_cast<uint16_t>(payloadLen);
288   loc += payloadLen;
289   addTransportFooterToBuf(mBuf, &loc);
290 
291   EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, partLenHeader));
292   EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_HEADER);
293   EXPECT_EQ(mTransportContext.rxHeader.length, payloadLen);
294   endAndValidatePacket(&mTransportContext);
295 
296   chppWorkThreadStop(&mTransportContext);
297   t1.join();
298 }
299 
300 /**
301  * End of Packet Link Notification during payload
302  */
TEST_F(TransportTests,LinkSendDonePayload)303 TEST_F(TransportTests, LinkSendDonePayload) {
304   size_t payloadLen = 1000;
305   size_t partLenPayload = 500;
306 
307   mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
308   mTransportContext.txStatus.hasPacketsToSend = true;
309   std::thread t1(chppWorkThreadStart, &mTransportContext);
310   WaitForTransport(&mTransportContext);
311 
312   size_t loc = 0;
313   addPreambleToBuf(mBuf, &loc);
314   ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
315   transHeader->length = static_cast<uint16_t>(payloadLen);
316   loc += payloadLen;
317   addTransportFooterToBuf(mBuf, &loc);
318 
319   EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, partLenPayload));
320   EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PAYLOAD);
321   EXPECT_EQ(mTransportContext.rxHeader.length, payloadLen);
322   EXPECT_EQ(
323       mTransportContext.rxStatus.locInDatagram,
324       partLenPayload - CHPP_PREAMBLE_LEN_BYTES - sizeof(ChppTransportHeader));
325   EXPECT_EQ(mTransportContext.rxDatagram.length, payloadLen);
326   endAndValidatePacket(&mTransportContext);
327 
328   chppWorkThreadStop(&mTransportContext);
329   t1.join();
330 }
331 
332 /**
333  * End of Packet Link Notification during footer
334  */
TEST_F(TransportTests,LinkSendDoneFooter)335 TEST_F(TransportTests, LinkSendDoneFooter) {
336   size_t payloadLen = 1000;
337   size_t partLenFooter = CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) +
338                          payloadLen + sizeof(ChppTransportFooter) - 1;
339 
340   mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
341   mTransportContext.txStatus.hasPacketsToSend = true;
342   std::thread t1(chppWorkThreadStart, &mTransportContext);
343   WaitForTransport(&mTransportContext);
344 
345   size_t loc = 0;
346   addPreambleToBuf(mBuf, &loc);
347   ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
348   transHeader->length = static_cast<uint16_t>(payloadLen);
349   loc += payloadLen;
350   addTransportFooterToBuf(mBuf, &loc);
351 
352   EXPECT_FALSE(chppRxDataCb(&mTransportContext, mBuf, partLenFooter));
353   EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_FOOTER);
354   EXPECT_EQ(mTransportContext.rxHeader.length, payloadLen);
355   EXPECT_EQ(mTransportContext.rxStatus.locInDatagram, payloadLen);
356   EXPECT_EQ(mTransportContext.rxDatagram.length, payloadLen);
357   endAndValidatePacket(&mTransportContext);
358 
359   chppWorkThreadStop(&mTransportContext);
360   t1.join();
361 }
362 
TEST_P(TransportTests,EnqueueDatagrams)363 TEST_P(TransportTests, EnqueueDatagrams) {
364   size_t len = static_cast<size_t>(GetParam());
365 
366   if (len <= CHPP_TX_DATAGRAM_QUEUE_LEN) {
367     // Add (len) datagrams of various length to queue
368 
369     int fr = 0;
370 
371     for (int j = 0; j == CHPP_TX_DATAGRAM_QUEUE_LEN; j++) {
372       for (size_t i = 1; i <= len; i++) {
373         uint8_t *mBuf = (uint8_t *)chppMalloc(i + 100);
374         EXPECT_TRUE(
375             chppEnqueueTxDatagramOrFail(&mTransportContext, mBuf, i + 100));
376 
377         EXPECT_EQ(mTransportContext.txDatagramQueue.pending, i);
378         EXPECT_EQ(mTransportContext.txDatagramQueue.front, fr);
379         EXPECT_EQ(mTransportContext.txDatagramQueue
380                       .datagram[(i - 1 + fr) % CHPP_TX_DATAGRAM_QUEUE_LEN]
381                       .length,
382                   i + 100);
383       }
384 
385       if (mTransportContext.txDatagramQueue.pending ==
386           CHPP_TX_DATAGRAM_QUEUE_LEN) {
387         uint8_t *mBuf = (uint8_t *)chppMalloc(100);
388         EXPECT_FALSE(
389             chppEnqueueTxDatagramOrFail(&mTransportContext, mBuf, 100));
390         CHPP_FREE_AND_NULLIFY(mBuf);
391       }
392 
393       for (size_t i = len; i > 0; i--) {
394         fr++;
395         fr %= CHPP_TX_DATAGRAM_QUEUE_LEN;
396 
397         EXPECT_TRUE(chppDequeueTxDatagram(&mTransportContext));
398 
399         EXPECT_EQ(mTransportContext.txDatagramQueue.front, fr);
400         EXPECT_EQ(mTransportContext.txDatagramQueue.pending, i - 1);
401       }
402 
403       EXPECT_FALSE(chppDequeueTxDatagram(&mTransportContext));
404 
405       EXPECT_EQ(mTransportContext.txDatagramQueue.front, fr);
406       EXPECT_EQ(mTransportContext.txDatagramQueue.pending, 0);
407     }
408   }
409 }
410 
411 /**
412  * Loopback testing with various length payloads of zeros
413  */
TEST_P(TransportTests,LoopbackPayloadOfZeros)414 TEST_P(TransportTests, LoopbackPayloadOfZeros) {
415   mTransportContext.rxStatus.state = CHPP_STATE_PREAMBLE;
416   size_t len = static_cast<size_t>(GetParam());
417 
418   mTransportContext.txStatus.hasPacketsToSend = true;
419   std::thread t1(chppWorkThreadStart, &mTransportContext);
420   WaitForTransport(&mTransportContext);
421   chppWorkThreadStop(&mTransportContext);
422   t1.join();
423 
424   if (len > 1 && len <= kMaxChunkSize) {
425     // Loopback App header (only 2 fields required)
426     mBuf[0] = CHPP_HANDLE_LOOPBACK;
427     mBuf[1] = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
428 
429     EXPECT_TRUE(chppDispatchLoopbackClientRequest(&mAppContext, mBuf, len));
430 
431     uint16_t end = (mTransportContext.txDatagramQueue.front +
432                     mTransportContext.txDatagramQueue.pending - 1) %
433                    CHPP_TX_DATAGRAM_QUEUE_LEN;
434 
435     EXPECT_EQ(mTransportContext.txDatagramQueue.datagram[end].length, len);
436     EXPECT_EQ(mTransportContext.txDatagramQueue.datagram[end].payload[0],
437               CHPP_HANDLE_LOOPBACK);
438     EXPECT_EQ(mTransportContext.txDatagramQueue.datagram[end].payload[1],
439               CHPP_MESSAGE_TYPE_SERVICE_RESPONSE);
440   }
441 }
442 
443 /**
444  * Discovery service + Transaction ID
445  */
TEST_P(TransportTests,DiscoveryAndTransactionID)446 TEST_P(TransportTests, DiscoveryAndTransactionID) {
447   uint8_t transactionID = static_cast<uint8_t>(GetParam());
448   size_t len = 0;
449 
450   mTransportContext.txStatus.hasPacketsToSend = true;
451   std::thread t1(chppWorkThreadStart, &mTransportContext);
452   WaitForTransport(&mTransportContext);
453   chppWorkThreadStop(&mTransportContext);
454   t1.join();
455 
456   ChppAppHeader *appHeader = addAppHeaderToBuf(mBuf, &len);
457   appHeader->handle = CHPP_HANDLE_DISCOVERY;
458   appHeader->transaction = transactionID;
459   appHeader->command = CHPP_DISCOVERY_COMMAND_DISCOVER_ALL;
460 
461   EXPECT_TRUE(chppDispatchDiscoveryClientRequest(&mAppContext, mBuf, len));
462 
463   uint16_t end = (mTransportContext.txDatagramQueue.front +
464                   mTransportContext.txDatagramQueue.pending - 1) %
465                  CHPP_TX_DATAGRAM_QUEUE_LEN;
466 
467   struct ChppAppHeader *responseHeader =
468       (ChppAppHeader *)mTransportContext.txDatagramQueue.datagram[end].payload;
469 
470   EXPECT_EQ(responseHeader->handle, CHPP_HANDLE_DISCOVERY);
471   EXPECT_EQ(responseHeader->type, CHPP_MESSAGE_TYPE_SERVICE_RESPONSE);
472   EXPECT_EQ(responseHeader->transaction, transactionID);
473   EXPECT_EQ(responseHeader->error, CHPP_APP_ERROR_NONE);
474   EXPECT_EQ(responseHeader->command, CHPP_DISCOVERY_COMMAND_DISCOVER_ALL);
475 
476   // Decode discovery response
477   ChppServiceDescriptor *services =
478       (ChppServiceDescriptor *)&mTransportContext.txDatagramQueue.datagram[end]
479           .payload[sizeof(ChppAppHeader)];
480 
481   // Check total length (and implicit service count)
482   EXPECT_EQ(
483       mTransportContext.txDatagramQueue.datagram[end].length,
484       sizeof(ChppAppHeader) + kServiceCount * sizeof(ChppServiceDescriptor));
485 
486   // Check service configuration response
487   ChppServiceDescriptor wwanServiceDescriptor = {};
488   static const uint8_t uuid[CHPP_SERVICE_UUID_LEN] = CHPP_UUID_WWAN_STANDARD;
489   memcpy(&wwanServiceDescriptor.uuid, &uuid,
490          sizeof(wwanServiceDescriptor.uuid));
491   static const char name[CHPP_SERVICE_NAME_MAX_LEN] = "WWAN";
492   memcpy(&wwanServiceDescriptor.name, &name,
493          sizeof(wwanServiceDescriptor.name));
494   wwanServiceDescriptor.version.major = 1;
495   wwanServiceDescriptor.version.minor = 0;
496   wwanServiceDescriptor.version.patch = 0;
497 
498   EXPECT_EQ(std::memcmp(services[0].uuid, wwanServiceDescriptor.uuid,
499                         sizeof(wwanServiceDescriptor.uuid)),
500             0);
501   EXPECT_EQ(std::memcmp(services[0].name, wwanServiceDescriptor.name,
502                         sizeof(wwanServiceDescriptor.name)),
503             0);
504   EXPECT_EQ(services[0].version.major, wwanServiceDescriptor.version.major);
505   EXPECT_EQ(services[0].version.minor, wwanServiceDescriptor.version.minor);
506   EXPECT_EQ(services[0].version.patch, wwanServiceDescriptor.version.patch);
507 }
508 
509 /**
510  * CRC-32 calculation for several pre-known test vectors.
511  */
TEST_F(TransportTests,CRC32Basic)512 TEST_F(TransportTests, CRC32Basic) {
513   static const char kTest1Str[] = "Hello World Test!";
514   static const uint8_t *kTest1 = (const uint8_t *)kTest1Str;
515   EXPECT_EQ(chppCrc32(0, kTest1, 17), 0x613B1D74);
516   EXPECT_EQ(chppCrc32(0, kTest1, 16), 0x5F88D7D9);
517   EXPECT_EQ(chppCrc32(0, kTest1, 1), 0xAA05262F);
518   EXPECT_EQ(chppCrc32(0, kTest1, 0), 0x00000000);
519 
520   static const uint8_t kTest2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
521   EXPECT_EQ(chppCrc32(0, kTest2, 6), 0x41D9ED00);
522   EXPECT_EQ(chppCrc32(0, kTest2, 5), 0xD2FD1072);
523   EXPECT_EQ(chppCrc32(0, kTest2, 4), 0xFFFFFFFF);
524   EXPECT_EQ(chppCrc32(0, kTest2, 3), 0xFFFFFF00);
525   EXPECT_EQ(chppCrc32(0, kTest2, 2), 0xFFFF0000);
526   EXPECT_EQ(chppCrc32(0, kTest2, 1), 0xFF000000);
527   EXPECT_EQ(chppCrc32(0, kTest2, 0), 0x00000000);
528 
529   static const char kTest3Str[] = "123456789";
530   static const uint8_t *kTest3 = (const uint8_t *)kTest3Str;
531   EXPECT_EQ(chppCrc32(0, kTest3, 9), 0xCBF43926);
532 
533   static const uint8_t kTest4[] = {0x00, 0x00, 0x00, 0x00};
534   EXPECT_EQ(chppCrc32(0, kTest4, sizeof(kTest4)), 0x2144DF1C);
535 
536   static const uint8_t kTest5[] = {0xF2, 0x01, 0x83};
537   EXPECT_EQ(chppCrc32(0, kTest5, sizeof(kTest5)), 0x24AB9D77);
538 
539   static const uint8_t kTest6[] = {0x0F, 0xAA, 0x00, 0x55};
540   EXPECT_EQ(chppCrc32(0, kTest6, sizeof(kTest6)), 0xB6C9B287);
541 
542   static const uint8_t kTest7[] = {0x00, 0xFF, 0x55, 0x11};
543   EXPECT_EQ(chppCrc32(0, kTest7, sizeof(kTest7)), 0x32A06212);
544 
545   static const uint8_t kTest8[] = {0x33, 0x22, 0x55, 0xAA, 0xBB,
546                                    0xCC, 0xDD, 0xEE, 0xFF};
547   EXPECT_EQ(chppCrc32(0, kTest8, sizeof(kTest8)), 0xB0AE863D);
548 
549   static const uint8_t kTest9[] = {0x92, 0x6B, 0x55};
550   EXPECT_EQ(chppCrc32(0, kTest9, sizeof(kTest9)), 0x9CDEA29B);
551 }
552 
553 /**
554  * CRC-32 calculation for daisy-chained input.
555  */
TEST_F(TransportTests,CRC32DaisyChained)556 TEST_F(TransportTests, CRC32DaisyChained) {
557   static const size_t kMaxLen = 10000;
558   uint8_t test[kMaxLen];
559   // Populate test with 8-bit LFSR
560   // Feedback polynomial is x^8 + x^6 + x^5 + x^4 + 1
561   static uint8_t lfsr = 1;
562   for (size_t i = 0; i < kMaxLen; i++) {
563     test[i] = lfsr;
564     lfsr = (lfsr >> 1) |
565            (((lfsr << 7) ^ (lfsr << 5) ^ (lfsr << 4) ^ (lfsr << 3)) & 0x80);
566   }
567 
568   for (size_t len = 0; len < kMaxLen; len += 1000) {
569     uint32_t fullCRC = chppCrc32(0, &test[0], len);
570     for (size_t partition = 0; partition <= len; partition++) {
571       uint32_t partialCRC = chppCrc32(0, &test[0], partition);
572       EXPECT_EQ(chppCrc32(partialCRC, &test[partition], len - partition),
573                 fullCRC);
574     }
575   }
576 }
577 
578 /**
579  * WWAN service Open and GetCapabilities.
580  */
TEST_F(TransportTests,WwanOpen)581 TEST_F(TransportTests, WwanOpen) {
582   mTransportContext.txStatus.hasPacketsToSend = true;
583   std::thread t1(chppWorkThreadStart, &mTransportContext);
584   WaitForTransport(&mTransportContext);
585 
586   uint8_t ackSeq = 1;
587   uint8_t seq = 0;
588   uint8_t handle = CHPP_HANDLE_NEGOTIATED_RANGE_START;
589   uint8_t transactionID = 0;
590   size_t len = 0;
591 
592   EXPECT_EQ(findServiceHandle(&mAppContext, "WWAN", &handle), true);
593 
594   openService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
595               transactionID++, CHPP_WWAN_OPEN, gChppLinuxLinkContext);
596 
597   addPreambleToBuf(mBuf, &len);
598 
599   uint16_t command = CHPP_WWAN_GET_CAPABILITIES;
600   sendCommandToService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
601                        transactionID++, command, gChppLinuxLinkContext);
602 
603   size_t responseLoc = sizeof(ChppTestResponse);
604 
605   // Validate capabilities
606   uint32_t *capabilities = (uint32_t *)&gChppLinuxLinkContext.buf[responseLoc];
607   responseLoc += sizeof(uint32_t);
608 
609   // Cleanup
610   chppWorkThreadStop(&mTransportContext);
611   t1.join();
612 
613   uint32_t capabilitySet = CHRE_WWAN_GET_CELL_INFO;
614   EXPECT_EQ((*capabilities) & ~(capabilitySet), 0);
615 
616   // Check total length
617   EXPECT_EQ(responseLoc, CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) +
618                              sizeof(ChppWwanGetCapabilitiesResponse));
619 }
620 
621 /**
622  * WiFi service Open and GetCapabilities.
623  */
TEST_F(TransportTests,WifiOpen)624 TEST_F(TransportTests, WifiOpen) {
625   mTransportContext.txStatus.hasPacketsToSend = true;
626   std::thread t1(chppWorkThreadStart, &mTransportContext);
627   WaitForTransport(&mTransportContext);
628 
629   uint8_t ackSeq = 1;
630   uint8_t seq = 0;
631   uint8_t handle = CHPP_HANDLE_NEGOTIATED_RANGE_START + 1;
632   uint8_t transactionID = 0;
633 
634   EXPECT_EQ(findServiceHandle(&mAppContext, "WiFi", &handle), true);
635 
636   openService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
637               transactionID++, CHPP_WIFI_OPEN, gChppLinuxLinkContext);
638 
639   uint16_t command = CHPP_WIFI_GET_CAPABILITIES;
640   sendCommandToService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
641                        transactionID++, command, gChppLinuxLinkContext);
642 
643   size_t responseLoc = sizeof(ChppTestResponse);
644 
645   // Cleanup
646   chppWorkThreadStop(&mTransportContext);
647   t1.join();
648 
649   // Validate capabilities
650   uint32_t *capabilities = (uint32_t *)&gChppLinuxLinkContext.buf[responseLoc];
651   responseLoc += sizeof(uint32_t);
652 
653   uint32_t capabilitySet = CHRE_WIFI_CAPABILITIES_SCAN_MONITORING |
654                            CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN |
655                            CHRE_WIFI_CAPABILITIES_RADIO_CHAIN_PREF |
656                            CHRE_WIFI_CAPABILITIES_RTT_RANGING |
657                            CHRE_WIFI_CAPABILITIES_NAN_SUB;
658   EXPECT_EQ((*capabilities) & ~(capabilitySet), 0);
659 
660   // Check total length
661   EXPECT_EQ(responseLoc, CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) +
662                              sizeof(ChppWwanGetCapabilitiesResponse));
663 }
664 
665 /**
666  * GNSS service Open and GetCapabilities.
667  */
TEST_F(TransportTests,GnssOpen)668 TEST_F(TransportTests, GnssOpen) {
669   mTransportContext.txStatus.hasPacketsToSend = true;
670   std::thread t1(chppWorkThreadStart, &mTransportContext);
671   WaitForTransport(&mTransportContext);
672 
673   uint8_t ackSeq = 1;
674   uint8_t seq = 0;
675   uint8_t handle = CHPP_HANDLE_NEGOTIATED_RANGE_START + 2;
676   uint8_t transactionID = 0;
677   size_t len = 0;
678 
679   EXPECT_EQ(findServiceHandle(&mAppContext, "GNSS", &handle), true);
680 
681   openService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
682               transactionID++, CHPP_GNSS_OPEN, gChppLinuxLinkContext);
683 
684   addPreambleToBuf(mBuf, &len);
685 
686   uint16_t command = CHPP_GNSS_GET_CAPABILITIES;
687   sendCommandToService(&mTransportContext, mBuf, ackSeq++, seq++, handle,
688                        transactionID++, command, gChppLinuxLinkContext);
689 
690   size_t responseLoc = sizeof(ChppTestResponse);
691 
692   // Cleanup
693   chppWorkThreadStop(&mTransportContext);
694   t1.join();
695 
696   // Validate capabilities
697   uint32_t *capabilities = (uint32_t *)&gChppLinuxLinkContext.buf[responseLoc];
698   responseLoc += sizeof(uint32_t);
699 
700   uint32_t capabilitySet =
701       CHRE_GNSS_CAPABILITIES_LOCATION | CHRE_GNSS_CAPABILITIES_MEASUREMENTS |
702       CHRE_GNSS_CAPABILITIES_GNSS_ENGINE_BASED_PASSIVE_LISTENER;
703   EXPECT_EQ((*capabilities) & ~(capabilitySet), 0);
704 
705   // Check total length
706   EXPECT_EQ(responseLoc, CHPP_PREAMBLE_LEN_BYTES + sizeof(ChppTransportHeader) +
707                              sizeof(ChppGnssGetCapabilitiesResponse));
708 }
709 
710 /**
711  * Discovery client.
712  */
TEST_F(TransportTests,Discovery)713 TEST_F(TransportTests, Discovery) {
714   size_t len = 0;
715 
716   mTransportContext.txStatus.hasPacketsToSend = true;
717   std::thread t1(chppWorkThreadStart, &mTransportContext);
718   WaitForTransport(&mTransportContext);
719 
720   addPreambleToBuf(mBuf, &len);
721 
722   ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &len);
723 
724   ChppAppHeader *appHeader = addAppHeaderToBuf(mBuf, &len);
725   appHeader->handle = CHPP_HANDLE_DISCOVERY;
726   appHeader->command = CHPP_DISCOVERY_COMMAND_DISCOVER_ALL;
727   appHeader->type = CHPP_MESSAGE_TYPE_SERVICE_RESPONSE;
728 
729   ChppServiceDescriptor wwanServiceDescriptor = {};
730   static const uint8_t uuid[CHPP_SERVICE_UUID_LEN] = CHPP_UUID_WWAN_STANDARD;
731   memcpy(&wwanServiceDescriptor.uuid, &uuid,
732          sizeof(wwanServiceDescriptor.uuid));
733   static const char name[CHPP_SERVICE_NAME_MAX_LEN] = "WWAN";
734   memcpy(&wwanServiceDescriptor.name, &name,
735          sizeof(wwanServiceDescriptor.name));
736   wwanServiceDescriptor.version.major = 1;
737   wwanServiceDescriptor.version.minor = 0;
738   wwanServiceDescriptor.version.patch = 0;
739 
740   memcpy(&mBuf[len], &wwanServiceDescriptor, sizeof(ChppServiceDescriptor));
741   len += sizeof(ChppServiceDescriptor);
742 
743   transHeader->length = static_cast<uint16_t>(
744       len - sizeof(ChppTransportHeader) - CHPP_PREAMBLE_LEN_BYTES);
745 
746   addTransportFooterToBuf(mBuf, &len);
747 
748   // Initialize clientIndexOfServiceIndex[0] to see if it correctly updated
749   // upon discovery
750   mAppContext.clientIndexOfServiceIndex[0] = CHPP_CLIENT_INDEX_NONE;
751 
752   // Send header + payload (if any) + footer
753   EXPECT_TRUE(chppRxDataCb(&mTransportContext, mBuf, len));
754 
755   // Cleanup
756   chppWorkThreadStop(&mTransportContext);
757   t1.join();
758 
759   // Check for correct state
760   EXPECT_EQ(mAppContext.clientIndexOfServiceIndex[0], 0);
761   uint8_t nextSeq = transHeader->seq + 1;
762   EXPECT_EQ(mTransportContext.rxStatus.expectedSeq, nextSeq);
763   EXPECT_EQ(mTransportContext.rxStatus.state, CHPP_STATE_PREAMBLE);
764 }
765 
766 /**
767  * Unopened clients should not crash upon an unsolicitated service response.
768  */
TEST_F(TransportTests,UnopenedClient)769 TEST_F(TransportTests, UnopenedClient) {
770   size_t len = 0;
771   uint8_t *buf = (uint8_t *)chppMalloc(100);
772 
773   mTransportContext.txStatus.hasPacketsToSend = true;
774   std::thread t1(chppWorkThreadStart, &mTransportContext);
775   WaitForTransport(&mTransportContext);
776   chppWorkThreadStop(&mTransportContext);
777   t1.join();
778 
779   ChppAppHeader *appHeader = addAppHeaderToBuf(buf, &len);
780   appHeader->handle = CHPP_HANDLE_NEGOTIATED_RANGE_START + 1;
781   appHeader->command = CHPP_WIFI_CONFIGURE_SCAN_MONITOR_ASYNC;
782   appHeader->type = CHPP_MESSAGE_TYPE_SERVICE_RESPONSE;
783   len = sizeof(struct ChppWifiConfigureScanMonitorAsyncResponse);
784 
785   ASSERT_EQ(mAppContext.registeredServiceCount, kServiceCount);
786 
787   chppAppProcessRxDatagram(&mAppContext, buf, len);
788 
789   EXPECT_EQ(mTransportContext.txStatus.packetCodeToSend,
790             CHPP_TRANSPORT_ERROR_APPLAYER);
791 }
792 
TEST_F(TransportTests,DiscardedPacketTest)793 TEST_F(TransportTests, DiscardedPacketTest) {
794   mTransportContext.txStatus.hasPacketsToSend = true;
795   std::thread t1(chppWorkThreadStart, &mTransportContext);
796   WaitForTransport(&mTransportContext);
797 
798   // Send packet to RX thread after manually setting to resetting state.
799   // We expect this packet to get dropped, but this test checks for any
800   // problematic behavior (e.g. memory leaks).
801   mTransportContext.resetState = CHPP_RESET_STATE_RESETTING;
802 
803   size_t loc = 0;
804   addPreambleToBuf(mBuf, &loc);
805   ChppTransportHeader *transHeader = addTransportHeaderToBuf(mBuf, &loc);
806 
807   ChppAppHeader *appHeader = addAppHeaderToBuf(mBuf, &loc);
808   appHeader->handle = CHPP_HANDLE_DISCOVERY;
809   appHeader->command = CHPP_DISCOVERY_COMMAND_DISCOVER_ALL;
810   appHeader->type = CHPP_MESSAGE_TYPE_SERVICE_RESPONSE;
811 
812   ChppServiceDescriptor wwanServiceDescriptor = {};
813   static const uint8_t uuid[CHPP_SERVICE_UUID_LEN] = CHPP_UUID_WWAN_STANDARD;
814   memcpy(&wwanServiceDescriptor.uuid, &uuid,
815          sizeof(wwanServiceDescriptor.uuid));
816   static const char name[CHPP_SERVICE_NAME_MAX_LEN] = "WWAN";
817   memcpy(&wwanServiceDescriptor.name, &name,
818          sizeof(wwanServiceDescriptor.name));
819   wwanServiceDescriptor.version.major = 1;
820   wwanServiceDescriptor.version.minor = 0;
821   wwanServiceDescriptor.version.patch = 0;
822 
823   memcpy(&mBuf[loc], &wwanServiceDescriptor, sizeof(ChppServiceDescriptor));
824   loc += sizeof(ChppServiceDescriptor);
825 
826   transHeader->length = static_cast<uint16_t>(
827       loc - sizeof(ChppTransportHeader) - CHPP_PREAMBLE_LEN_BYTES);
828 
829   addTransportFooterToBuf(mBuf, &loc);
830 
831   mAppContext.clientIndexOfServiceIndex[0] = CHPP_CLIENT_INDEX_NONE;
832 
833   EXPECT_TRUE(chppRxDataCb(&mTransportContext, mBuf, loc));
834 
835   chppWorkThreadStop(&mTransportContext);
836   t1.join();
837 }
838 
839 /*
840  * Correctly handle messages directed to clients / services with an invalid
841  * handle number.
842  */
messageToInvalidHandle(ChppTransportState * transportContext,uint8_t type)843 void messageToInvalidHandle(ChppTransportState *transportContext,
844                             uint8_t type) {
845   size_t len = 0;
846   uint8_t *buf = (uint8_t *)chppMalloc(100);
847 
848   transportContext->txStatus.hasPacketsToSend = true;
849   std::thread t1(chppWorkThreadStart, transportContext);
850   WaitForTransport(transportContext);
851   chppWorkThreadStop(transportContext);
852   t1.join();
853 
854   ChppAppHeader *appHeader = addAppHeaderToBuf(buf, &len);
855   appHeader->handle =
856       CHPP_HANDLE_NEGOTIATED_RANGE_START +
857       MAX(CHPP_MAX_REGISTERED_CLIENTS, CHPP_MAX_REGISTERED_SERVICES);
858   appHeader->type = type;
859   len = sizeof(struct ChppAppHeader);
860 
861   chppAppProcessRxDatagram(transportContext->appContext, buf, len);
862 
863   EXPECT_EQ(transportContext->txStatus.packetCodeToSend,
864             CHPP_TRANSPORT_ERROR_APPLAYER);
865 }
866 
TEST_F(TransportTests,RequestToInvalidService)867 TEST_F(TransportTests, RequestToInvalidService) {
868   messageToInvalidHandle(&mTransportContext, CHPP_MESSAGE_TYPE_CLIENT_REQUEST);
869 }
870 
TEST_F(TransportTests,ResponseToInvalidClient)871 TEST_F(TransportTests, ResponseToInvalidClient) {
872   messageToInvalidHandle(&mTransportContext,
873                          CHPP_MESSAGE_TYPE_SERVICE_RESPONSE);
874 }
875 
TEST_F(TransportTests,NotificationToInvalidService)876 TEST_F(TransportTests, NotificationToInvalidService) {
877   messageToInvalidHandle(&mTransportContext,
878                          CHPP_MESSAGE_TYPE_CLIENT_NOTIFICATION);
879 }
880 
TEST_F(TransportTests,NotificationToInvalidClient)881 TEST_F(TransportTests, NotificationToInvalidClient) {
882   messageToInvalidHandle(&mTransportContext,
883                          CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION);
884 }
885 
TEST_F(TransportTests,WorkMonitorInvoked)886 TEST_F(TransportTests, WorkMonitorInvoked) {
887   // Send message to spin work thread so it interacts with the work monitor
888   messageToInvalidHandle(&mTransportContext,
889                          CHPP_MESSAGE_TYPE_SERVICE_NOTIFICATION);
890 
891   // 1 pre/post call for executing the work and 1 for shutting down the thread.
892   EXPECT_EQ(mTransportContext.workMonitor.numPreProcessCalls, 2);
893   EXPECT_EQ(mTransportContext.workMonitor.numPostProcessCalls, 2);
894 }
895 
896 INSTANTIATE_TEST_SUITE_P(TransportTestRange, TransportTests,
897                          testing::ValuesIn(kChunkSizes));
898 
899 }  // namespace chpp::test
900