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