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