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