1 /* 2 * Copyright (C) 2016 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 <asm-generic/mman.h> 18 #include <gtest/gtest.h> 19 #include <atomic> 20 #include <cstdlib> 21 #include <sstream> 22 #include <thread> 23 #include <fmq/MessageQueue.h> 24 #include <fmq/EventFlag.h> 25 26 enum EventFlagBits : uint32_t { 27 kFmqNotEmpty = 1 << 0, 28 kFmqNotFull = 1 << 1, 29 }; 30 31 typedef android::hardware::MessageQueue<uint8_t, android::hardware::kSynchronizedReadWrite> 32 MessageQueueSync; 33 typedef android::hardware::MessageQueue<uint8_t, android::hardware::kUnsynchronizedWrite> 34 MessageQueueUnsync; 35 36 class SynchronizedReadWrites : public ::testing::Test { 37 protected: 38 virtual void TearDown() { 39 delete mQueue; 40 } 41 42 virtual void SetUp() { 43 static constexpr size_t kNumElementsInQueue = 2048; 44 mQueue = new (std::nothrow) MessageQueueSync(kNumElementsInQueue); 45 ASSERT_NE(nullptr, mQueue); 46 ASSERT_TRUE(mQueue->isValid()); 47 mNumMessagesMax = mQueue->getQuantumCount(); 48 ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax); 49 } 50 51 MessageQueueSync* mQueue = nullptr; 52 size_t mNumMessagesMax = 0; 53 }; 54 55 class UnsynchronizedWrite : public ::testing::Test { 56 protected: 57 virtual void TearDown() { 58 delete mQueue; 59 } 60 61 virtual void SetUp() { 62 static constexpr size_t kNumElementsInQueue = 2048; 63 mQueue = new (std::nothrow) MessageQueueUnsync(kNumElementsInQueue); 64 ASSERT_NE(nullptr, mQueue); 65 ASSERT_TRUE(mQueue->isValid()); 66 mNumMessagesMax = mQueue->getQuantumCount(); 67 ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax); 68 } 69 70 MessageQueueUnsync* mQueue = nullptr; 71 size_t mNumMessagesMax = 0; 72 }; 73 74 class BlockingReadWrites : public ::testing::Test { 75 protected: 76 virtual void TearDown() { 77 delete mQueue; 78 } 79 virtual void SetUp() { 80 static constexpr size_t kNumElementsInQueue = 2048; 81 mQueue = new (std::nothrow) MessageQueueSync(kNumElementsInQueue); 82 ASSERT_NE(nullptr, mQueue); 83 ASSERT_TRUE(mQueue->isValid()); 84 mNumMessagesMax = mQueue->getQuantumCount(); 85 ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax); 86 /* 87 * Initialize the EventFlag word to indicate Queue is not full. 88 */ 89 std::atomic_init(&mFw, static_cast<uint32_t>(kFmqNotFull)); 90 } 91 92 MessageQueueSync* mQueue; 93 std::atomic<uint32_t> mFw; 94 size_t mNumMessagesMax = 0; 95 }; 96 97 class QueueSizeOdd : public ::testing::Test { 98 protected: 99 virtual void TearDown() { 100 delete mQueue; 101 } 102 virtual void SetUp() { 103 static constexpr size_t kNumElementsInQueue = 2049; 104 mQueue = new (std::nothrow) MessageQueueSync(kNumElementsInQueue, 105 true /* configureEventFlagWord */); 106 ASSERT_NE(nullptr, mQueue); 107 ASSERT_TRUE(mQueue->isValid()); 108 mNumMessagesMax = mQueue->getQuantumCount(); 109 ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax); 110 auto evFlagWordPtr = mQueue->getEventFlagWord(); 111 ASSERT_NE(nullptr, evFlagWordPtr); 112 /* 113 * Initialize the EventFlag word to indicate Queue is not full. 114 */ 115 std::atomic_init(evFlagWordPtr, static_cast<uint32_t>(kFmqNotFull)); 116 } 117 118 MessageQueueSync* mQueue; 119 size_t mNumMessagesMax = 0; 120 }; 121 122 class BadQueueConfig: public ::testing::Test { 123 }; 124 125 /* 126 * Utility function to initialize data to be written to the FMQ 127 */ 128 inline void initData(uint8_t* data, size_t count) { 129 for (size_t i = 0; i < count; i++) { 130 data[i] = i & 0xFF; 131 } 132 } 133 134 /* 135 * This thread will attempt to read and block. When wait returns 136 * it checks if the kFmqNotEmpty bit is actually set. 137 * If the read is succesful, it signals Wake to kFmqNotFull. 138 */ 139 void ReaderThreadBlocking( 140 android::hardware::MessageQueue<uint8_t, 141 android::hardware::kSynchronizedReadWrite>* fmq, 142 std::atomic<uint32_t>* fwAddr) { 143 const size_t dataLen = 64; 144 uint8_t data[dataLen]; 145 android::hardware::EventFlag* efGroup = nullptr; 146 android::status_t status = android::hardware::EventFlag::createEventFlag(fwAddr, &efGroup); 147 ASSERT_EQ(android::NO_ERROR, status); 148 ASSERT_NE(nullptr, efGroup); 149 150 while (true) { 151 uint32_t efState = 0; 152 android::status_t ret = efGroup->wait(kFmqNotEmpty, 153 &efState, 154 5000000000 /* timeoutNanoSeconds */); 155 /* 156 * Wait should not time out here after 5s 157 */ 158 ASSERT_NE(android::TIMED_OUT, ret); 159 160 if ((efState & kFmqNotEmpty) && fmq->read(data, dataLen)) { 161 efGroup->wake(kFmqNotFull); 162 break; 163 } 164 } 165 166 status = android::hardware::EventFlag::deleteEventFlag(&efGroup); 167 ASSERT_EQ(android::NO_ERROR, status); 168 } 169 170 /* 171 * This thread will attempt to read and block using the readBlocking() API and 172 * passes in a pointer to an EventFlag object. 173 */ 174 void ReaderThreadBlocking2( 175 android::hardware::MessageQueue<uint8_t, 176 android::hardware::kSynchronizedReadWrite>* fmq, 177 std::atomic<uint32_t>* fwAddr) { 178 const size_t dataLen = 64; 179 uint8_t data[dataLen]; 180 android::hardware::EventFlag* efGroup = nullptr; 181 android::status_t status = android::hardware::EventFlag::createEventFlag(fwAddr, &efGroup); 182 ASSERT_EQ(android::NO_ERROR, status); 183 ASSERT_NE(nullptr, efGroup); 184 bool ret = fmq->readBlocking(data, 185 dataLen, 186 static_cast<uint32_t>(kFmqNotFull), 187 static_cast<uint32_t>(kFmqNotEmpty), 188 5000000000 /* timeOutNanos */, 189 efGroup); 190 ASSERT_TRUE(ret); 191 status = android::hardware::EventFlag::deleteEventFlag(&efGroup); 192 ASSERT_EQ(android::NO_ERROR, status); 193 } 194 195 196 TEST_F(BadQueueConfig, QueueSizeTooLarge) { 197 typedef android::hardware::MessageQueue<uint16_t, android::hardware::kSynchronizedReadWrite> 198 MessageQueueSync16; 199 size_t numElementsInQueue = SIZE_MAX / sizeof(uint16_t) + 1; 200 MessageQueueSync16 * fmq = new (std::nothrow) MessageQueueSync16(numElementsInQueue); 201 ASSERT_NE(nullptr, fmq); 202 /* 203 * Should fail due to size being too large to fit into size_t. 204 */ 205 ASSERT_FALSE(fmq->isValid()); 206 } 207 208 /* 209 * Test that basic blocking works. This test uses the non-blocking read()/write() 210 * APIs. 211 */ 212 TEST_F(BlockingReadWrites, SmallInputTest1) { 213 const size_t dataLen = 64; 214 uint8_t data[dataLen] = {0}; 215 216 android::hardware::EventFlag* efGroup = nullptr; 217 android::status_t status = android::hardware::EventFlag::createEventFlag(&mFw, &efGroup); 218 219 ASSERT_EQ(android::NO_ERROR, status); 220 ASSERT_NE(nullptr, efGroup); 221 222 /* 223 * Start a thread that will try to read and block on kFmqNotEmpty. 224 */ 225 std::thread Reader(ReaderThreadBlocking, mQueue, &mFw); 226 struct timespec waitTime = {0, 100 * 1000000}; 227 ASSERT_EQ(0, nanosleep(&waitTime, NULL)); 228 229 /* 230 * After waiting for some time write into the FMQ 231 * and call Wake on kFmqNotEmpty. 232 */ 233 ASSERT_TRUE(mQueue->write(data, dataLen)); 234 status = efGroup->wake(kFmqNotEmpty); 235 ASSERT_EQ(android::NO_ERROR, status); 236 237 ASSERT_EQ(0, nanosleep(&waitTime, NULL)); 238 Reader.join(); 239 240 status = android::hardware::EventFlag::deleteEventFlag(&efGroup); 241 ASSERT_EQ(android::NO_ERROR, status); 242 } 243 244 /* 245 * Test that basic blocking works. This test uses the 246 * writeBlocking()/readBlocking() APIs. 247 */ 248 TEST_F(BlockingReadWrites, SmallInputTest2) { 249 const size_t dataLen = 64; 250 uint8_t data[dataLen] = {0}; 251 252 android::hardware::EventFlag* efGroup = nullptr; 253 android::status_t status = android::hardware::EventFlag::createEventFlag(&mFw, &efGroup); 254 255 ASSERT_EQ(android::NO_ERROR, status); 256 ASSERT_NE(nullptr, efGroup); 257 258 /* 259 * Start a thread that will try to read and block on kFmqNotEmpty. It will 260 * call wake() on kFmqNotFull when the read is successful. 261 */ 262 std::thread Reader(ReaderThreadBlocking2, mQueue, &mFw); 263 bool ret = mQueue->writeBlocking(data, 264 dataLen, 265 static_cast<uint32_t>(kFmqNotFull), 266 static_cast<uint32_t>(kFmqNotEmpty), 267 5000000000 /* timeOutNanos */, 268 efGroup); 269 ASSERT_TRUE(ret); 270 Reader.join(); 271 272 status = android::hardware::EventFlag::deleteEventFlag(&efGroup); 273 ASSERT_EQ(android::NO_ERROR, status); 274 } 275 276 /* 277 * Test that basic blocking times out as intended. 278 */ 279 TEST_F(BlockingReadWrites, BlockingTimeOutTest) { 280 android::hardware::EventFlag* efGroup = nullptr; 281 android::status_t status = android::hardware::EventFlag::createEventFlag(&mFw, &efGroup); 282 283 ASSERT_EQ(android::NO_ERROR, status); 284 ASSERT_NE(nullptr, efGroup); 285 286 /* Block on an EventFlag bit that no one will wake and time out in 1s */ 287 uint32_t efState = 0; 288 android::status_t ret = efGroup->wait(kFmqNotEmpty, 289 &efState, 290 1000000000 /* timeoutNanoSeconds */); 291 /* 292 * Wait should time out in a second. 293 */ 294 EXPECT_EQ(android::TIMED_OUT, ret); 295 296 status = android::hardware::EventFlag::deleteEventFlag(&efGroup); 297 ASSERT_EQ(android::NO_ERROR, status); 298 } 299 300 /* 301 * Test that odd queue sizes do not cause unaligned error 302 * on access to EventFlag object. 303 */ 304 TEST_F(QueueSizeOdd, EventFlagTest) { 305 const size_t dataLen = 64; 306 uint8_t data[dataLen] = {0}; 307 308 bool ret = mQueue->writeBlocking(data, 309 dataLen, 310 static_cast<uint32_t>(kFmqNotFull), 311 static_cast<uint32_t>(kFmqNotEmpty), 312 5000000000 /* timeOutNanos */); 313 ASSERT_TRUE(ret); 314 } 315 316 /* 317 * Verify that a few bytes of data can be successfully written and read. 318 */ 319 TEST_F(SynchronizedReadWrites, SmallInputTest1) { 320 const size_t dataLen = 16; 321 ASSERT_LE(dataLen, mNumMessagesMax); 322 uint8_t data[dataLen]; 323 324 initData(data, dataLen); 325 326 ASSERT_TRUE(mQueue->write(data, dataLen)); 327 uint8_t readData[dataLen] = {}; 328 ASSERT_TRUE(mQueue->read(readData, dataLen)); 329 ASSERT_EQ(0, memcmp(data, readData, dataLen)); 330 } 331 332 /* 333 * Verify that a few bytes of data can be successfully written and read using 334 * beginRead/beginWrite/CommitRead/CommitWrite 335 */ 336 TEST_F(SynchronizedReadWrites, SmallInputTest2) { 337 const size_t dataLen = 16; 338 ASSERT_LE(dataLen, mNumMessagesMax); 339 uint8_t data[dataLen]; 340 341 initData(data, dataLen); 342 343 MessageQueueSync::MemTransaction tx; 344 ASSERT_TRUE(mQueue->beginWrite(dataLen, &tx)); 345 346 ASSERT_TRUE(tx.copyTo(data, 0 /* startIdx */, dataLen)); 347 348 ASSERT_TRUE(mQueue->commitWrite(dataLen)); 349 350 uint8_t readData[dataLen] = {}; 351 352 ASSERT_TRUE(mQueue->beginRead(dataLen, &tx)); 353 354 ASSERT_TRUE(tx.copyFrom(readData, 0 /* startIdx */, dataLen)); 355 356 ASSERT_TRUE(mQueue->commitRead(dataLen)); 357 358 ASSERT_EQ(0, memcmp(data, readData, dataLen)); 359 } 360 361 /* 362 * Verify that a few bytes of data can be successfully written and read using 363 * beginRead/beginWrite/CommitRead/CommitWrite as well as getSlot(). 364 */ 365 TEST_F(SynchronizedReadWrites, SmallInputTest3) { 366 const size_t dataLen = 16; 367 ASSERT_LE(dataLen, mNumMessagesMax); 368 uint8_t data[dataLen]; 369 370 initData(data, dataLen); 371 MessageQueueSync::MemTransaction tx; 372 ASSERT_TRUE(mQueue->beginWrite(dataLen, &tx)); 373 374 auto first = tx.getFirstRegion(); 375 auto second = tx.getSecondRegion(); 376 377 ASSERT_EQ(first.getLength() + second.getLength(), dataLen); 378 for (size_t i = 0; i < dataLen; i++) { 379 uint8_t* ptr = tx.getSlot(i); 380 *ptr = data[i]; 381 } 382 383 ASSERT_TRUE(mQueue->commitWrite(dataLen)); 384 385 uint8_t readData[dataLen] = {}; 386 387 ASSERT_TRUE(mQueue->beginRead(dataLen, &tx)); 388 389 first = tx.getFirstRegion(); 390 second = tx.getSecondRegion(); 391 392 ASSERT_EQ(first.getLength() + second.getLength(), dataLen); 393 394 for (size_t i = 0; i < dataLen; i++) { 395 uint8_t* ptr = tx.getSlot(i); 396 readData[i] = *ptr; 397 } 398 399 ASSERT_TRUE(mQueue->commitRead(dataLen)); 400 401 ASSERT_EQ(0, memcmp(data, readData, dataLen)); 402 } 403 404 /* 405 * Verify that read() returns false when trying to read from an empty queue. 406 */ 407 TEST_F(SynchronizedReadWrites, ReadWhenEmpty1) { 408 ASSERT_EQ(0UL, mQueue->availableToRead()); 409 const size_t dataLen = 2; 410 ASSERT_LE(dataLen, mNumMessagesMax); 411 uint8_t readData[dataLen]; 412 ASSERT_FALSE(mQueue->read(readData, dataLen)); 413 } 414 415 /* 416 * Verify that beginRead() returns a MemTransaction object with null pointers when trying 417 * to read from an empty queue. 418 */ 419 TEST_F(SynchronizedReadWrites, ReadWhenEmpty2) { 420 ASSERT_EQ(0UL, mQueue->availableToRead()); 421 const size_t dataLen = 2; 422 ASSERT_LE(dataLen, mNumMessagesMax); 423 424 MessageQueueSync::MemTransaction tx; 425 ASSERT_FALSE(mQueue->beginRead(dataLen, &tx)); 426 427 auto first = tx.getFirstRegion(); 428 auto second = tx.getSecondRegion(); 429 430 ASSERT_EQ(nullptr, first.getAddress()); 431 ASSERT_EQ(nullptr, second.getAddress()); 432 } 433 434 /* 435 * Write the queue until full. Verify that another write is unsuccessful. 436 * Verify that availableToWrite() returns 0 as expected. 437 */ 438 TEST_F(SynchronizedReadWrites, WriteWhenFull1) { 439 ASSERT_EQ(0UL, mQueue->availableToRead()); 440 std::vector<uint8_t> data(mNumMessagesMax); 441 442 initData(&data[0], mNumMessagesMax); 443 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 444 ASSERT_EQ(0UL, mQueue->availableToWrite()); 445 ASSERT_FALSE(mQueue->write(&data[0], 1)); 446 447 std::vector<uint8_t> readData(mNumMessagesMax); 448 ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax)); 449 ASSERT_EQ(data, readData); 450 } 451 452 /* 453 * Write the queue until full. Verify that beginWrite() returns 454 * a MemTransaction object with null base pointers. 455 */ 456 TEST_F(SynchronizedReadWrites, WriteWhenFull2) { 457 ASSERT_EQ(0UL, mQueue->availableToRead()); 458 std::vector<uint8_t> data(mNumMessagesMax); 459 460 initData(&data[0], mNumMessagesMax); 461 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 462 ASSERT_EQ(0UL, mQueue->availableToWrite()); 463 464 MessageQueueSync::MemTransaction tx; 465 ASSERT_FALSE(mQueue->beginWrite(1, &tx)); 466 467 auto first = tx.getFirstRegion(); 468 auto second = tx.getSecondRegion(); 469 470 ASSERT_EQ(nullptr, first.getAddress()); 471 ASSERT_EQ(nullptr, second.getAddress()); 472 } 473 474 /* 475 * Write a chunk of data equal to the queue size. 476 * Verify that the write is successful and the subsequent read 477 * returns the expected data. 478 */ 479 TEST_F(SynchronizedReadWrites, LargeInputTest1) { 480 std::vector<uint8_t> data(mNumMessagesMax); 481 initData(&data[0], mNumMessagesMax); 482 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 483 std::vector<uint8_t> readData(mNumMessagesMax); 484 ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax)); 485 ASSERT_EQ(data, readData); 486 } 487 488 /* 489 * Attempt to write a chunk of data larger than the queue size. 490 * Verify that it fails. Verify that a subsequent read fails and 491 * the queue is still empty. 492 */ 493 TEST_F(SynchronizedReadWrites, LargeInputTest2) { 494 ASSERT_EQ(0UL, mQueue->availableToRead()); 495 const size_t dataLen = 4096; 496 ASSERT_GT(dataLen, mNumMessagesMax); 497 std::vector<uint8_t> data(dataLen); 498 499 initData(&data[0], dataLen); 500 ASSERT_FALSE(mQueue->write(&data[0], dataLen)); 501 std::vector<uint8_t> readData(mNumMessagesMax); 502 ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax)); 503 ASSERT_NE(data, readData); 504 ASSERT_EQ(0UL, mQueue->availableToRead()); 505 } 506 507 /* 508 * After the queue is full, try to write more data. Verify that 509 * the attempt returns false. Verify that the attempt did not 510 * affect the pre-existing data in the queue. 511 */ 512 TEST_F(SynchronizedReadWrites, LargeInputTest3) { 513 std::vector<uint8_t> data(mNumMessagesMax); 514 initData(&data[0], mNumMessagesMax); 515 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 516 ASSERT_FALSE(mQueue->write(&data[0], 1)); 517 std::vector<uint8_t> readData(mNumMessagesMax); 518 ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax)); 519 ASSERT_EQ(data, readData); 520 } 521 522 /* 523 * Verify that beginWrite() returns a MemTransaction with 524 * null base pointers when attempting to write data larger 525 * than the queue size. 526 */ 527 TEST_F(SynchronizedReadWrites, LargeInputTest4) { 528 ASSERT_EQ(0UL, mQueue->availableToRead()); 529 const size_t dataLen = 4096; 530 ASSERT_GT(dataLen, mNumMessagesMax); 531 532 MessageQueueSync::MemTransaction tx; 533 ASSERT_FALSE(mQueue->beginWrite(dataLen, &tx)); 534 535 auto first = tx.getFirstRegion(); 536 auto second = tx.getSecondRegion(); 537 538 ASSERT_EQ(nullptr, first.getAddress()); 539 ASSERT_EQ(nullptr, second.getAddress()); 540 } 541 542 /* 543 * Verify that multiple reads one after the other return expected data. 544 */ 545 TEST_F(SynchronizedReadWrites, MultipleRead) { 546 const size_t chunkSize = 100; 547 const size_t chunkNum = 5; 548 const size_t dataLen = chunkSize * chunkNum; 549 ASSERT_LE(dataLen, mNumMessagesMax); 550 uint8_t data[dataLen]; 551 552 initData(data, dataLen); 553 ASSERT_TRUE(mQueue->write(data, dataLen)); 554 uint8_t readData[dataLen] = {}; 555 for (size_t i = 0; i < chunkNum; i++) { 556 ASSERT_TRUE(mQueue->read(readData + i * chunkSize, chunkSize)); 557 } 558 ASSERT_EQ(0, memcmp(readData, data, dataLen)); 559 } 560 561 /* 562 * Verify that multiple writes one after the other happens correctly. 563 */ 564 TEST_F(SynchronizedReadWrites, MultipleWrite) { 565 const int chunkSize = 100; 566 const int chunkNum = 5; 567 const size_t dataLen = chunkSize * chunkNum; 568 ASSERT_LE(dataLen, mNumMessagesMax); 569 uint8_t data[dataLen]; 570 571 initData(data, dataLen); 572 for (unsigned int i = 0; i < chunkNum; i++) { 573 ASSERT_TRUE(mQueue->write(data + i * chunkSize, chunkSize)); 574 } 575 uint8_t readData[dataLen] = {}; 576 ASSERT_TRUE(mQueue->read(readData, dataLen)); 577 ASSERT_EQ(0, memcmp(readData, data, dataLen)); 578 } 579 580 /* 581 * Write enough messages into the FMQ to fill half of it 582 * and read back the same. 583 * Write mNumMessagesMax messages into the queue. This will cause a 584 * wrap around. Read and verify the data. 585 */ 586 TEST_F(SynchronizedReadWrites, ReadWriteWrapAround1) { 587 size_t numMessages = mNumMessagesMax - 1; 588 std::vector<uint8_t> data(mNumMessagesMax); 589 std::vector<uint8_t> readData(mNumMessagesMax); 590 initData(&data[0], mNumMessagesMax); 591 ASSERT_TRUE(mQueue->write(&data[0], numMessages)); 592 ASSERT_TRUE(mQueue->read(&readData[0], numMessages)); 593 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 594 ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax)); 595 ASSERT_EQ(data, readData); 596 } 597 598 /* 599 * Use beginRead/CommitRead/beginWrite/commitWrite APIs 600 * to test wrap arounds are handled correctly. 601 * Write enough messages into the FMQ to fill half of it 602 * and read back the same. 603 * Write mNumMessagesMax messages into the queue. This will cause a 604 * wrap around. Read and verify the data. 605 */ 606 TEST_F(SynchronizedReadWrites, ReadWriteWrapAround2) { 607 size_t dataLen = mNumMessagesMax - 1; 608 std::vector<uint8_t> data(mNumMessagesMax); 609 std::vector<uint8_t> readData(mNumMessagesMax); 610 initData(&data[0], mNumMessagesMax); 611 ASSERT_TRUE(mQueue->write(&data[0], dataLen)); 612 ASSERT_TRUE(mQueue->read(&readData[0], dataLen)); 613 614 /* 615 * The next write and read will have to deal with with wrap arounds. 616 */ 617 MessageQueueSync::MemTransaction tx; 618 ASSERT_TRUE(mQueue->beginWrite(mNumMessagesMax, &tx)); 619 620 auto first = tx.getFirstRegion(); 621 auto second = tx.getSecondRegion(); 622 623 ASSERT_EQ(first.getLength() + second.getLength(), mNumMessagesMax); 624 625 ASSERT_TRUE(tx.copyTo(&data[0], 0 /* startIdx */, mNumMessagesMax)); 626 627 ASSERT_TRUE(mQueue->commitWrite(mNumMessagesMax)); 628 629 ASSERT_TRUE(mQueue->beginRead(mNumMessagesMax, &tx)); 630 631 first = tx.getFirstRegion(); 632 second = tx.getSecondRegion(); 633 634 ASSERT_EQ(first.getLength() + second.getLength(), mNumMessagesMax); 635 636 ASSERT_TRUE(tx.copyFrom(&readData[0], 0 /* startIdx */, mNumMessagesMax)); 637 ASSERT_TRUE(mQueue->commitRead(mNumMessagesMax)); 638 639 ASSERT_EQ(data, readData); 640 } 641 642 /* 643 * Verify that a few bytes of data can be successfully written and read. 644 */ 645 TEST_F(UnsynchronizedWrite, SmallInputTest1) { 646 const size_t dataLen = 16; 647 ASSERT_LE(dataLen, mNumMessagesMax); 648 uint8_t data[dataLen]; 649 650 initData(data, dataLen); 651 ASSERT_TRUE(mQueue->write(data, dataLen)); 652 uint8_t readData[dataLen] = {}; 653 ASSERT_TRUE(mQueue->read(readData, dataLen)); 654 ASSERT_EQ(0, memcmp(data, readData, dataLen)); 655 } 656 657 /* 658 * Verify that read() returns false when trying to read from an empty queue. 659 */ 660 TEST_F(UnsynchronizedWrite, ReadWhenEmpty) { 661 ASSERT_EQ(0UL, mQueue->availableToRead()); 662 const size_t dataLen = 2; 663 ASSERT_TRUE(dataLen < mNumMessagesMax); 664 uint8_t readData[dataLen]; 665 ASSERT_FALSE(mQueue->read(readData, dataLen)); 666 } 667 668 /* 669 * Write the queue when full. Verify that a subsequent writes is succesful. 670 * Verify that availableToWrite() returns 0 as expected. 671 */ 672 TEST_F(UnsynchronizedWrite, WriteWhenFull1) { 673 ASSERT_EQ(0UL, mQueue->availableToRead()); 674 std::vector<uint8_t> data(mNumMessagesMax); 675 676 initData(&data[0], mNumMessagesMax); 677 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 678 ASSERT_EQ(0UL, mQueue->availableToWrite()); 679 ASSERT_TRUE(mQueue->write(&data[0], 1)); 680 681 std::vector<uint8_t> readData(mNumMessagesMax); 682 ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax)); 683 } 684 685 /* 686 * Write the queue when full. Verify that a subsequent writes 687 * using beginRead()/commitRead() is succesful. 688 * Verify that the next read fails as expected for unsynchronized flavor. 689 */ 690 TEST_F(UnsynchronizedWrite, WriteWhenFull2) { 691 ASSERT_EQ(0UL, mQueue->availableToRead()); 692 std::vector<uint8_t> data(mNumMessagesMax); 693 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 694 695 MessageQueueUnsync::MemTransaction tx; 696 ASSERT_TRUE(mQueue->beginWrite(1, &tx)); 697 698 ASSERT_EQ(tx.getFirstRegion().getLength(), 1U); 699 700 ASSERT_TRUE(tx.copyTo(&data[0], 0 /* startIdx */)); 701 702 ASSERT_TRUE(mQueue->commitWrite(1)); 703 704 std::vector<uint8_t> readData(mNumMessagesMax); 705 ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax)); 706 } 707 708 /* 709 * Write a chunk of data equal to the queue size. 710 * Verify that the write is successful and the subsequent read 711 * returns the expected data. 712 */ 713 TEST_F(UnsynchronizedWrite, LargeInputTest1) { 714 std::vector<uint8_t> data(mNumMessagesMax); 715 initData(&data[0], mNumMessagesMax); 716 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 717 std::vector<uint8_t> readData(mNumMessagesMax); 718 ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax)); 719 ASSERT_EQ(data, readData); 720 } 721 722 /* 723 * Attempt to write a chunk of data larger than the queue size. 724 * Verify that it fails. Verify that a subsequent read fails and 725 * the queue is still empty. 726 */ 727 TEST_F(UnsynchronizedWrite, LargeInputTest2) { 728 ASSERT_EQ(0UL, mQueue->availableToRead()); 729 const size_t dataLen = 4096; 730 ASSERT_GT(dataLen, mNumMessagesMax); 731 std::vector<uint8_t> data(dataLen); 732 initData(&data[0], dataLen); 733 ASSERT_FALSE(mQueue->write(&data[0], dataLen)); 734 std::vector<uint8_t> readData(mNumMessagesMax); 735 ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax)); 736 ASSERT_NE(data, readData); 737 ASSERT_EQ(0UL, mQueue->availableToRead()); 738 } 739 740 /* 741 * After the queue is full, try to write more data. Verify that 742 * the attempt is succesful. Verify that the read fails 743 * as expected. 744 */ 745 TEST_F(UnsynchronizedWrite, LargeInputTest3) { 746 std::vector<uint8_t> data(mNumMessagesMax); 747 initData(&data[0], mNumMessagesMax); 748 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 749 ASSERT_TRUE(mQueue->write(&data[0], 1)); 750 std::vector<uint8_t> readData(mNumMessagesMax); 751 ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax)); 752 } 753 754 /* 755 * Verify that multiple reads one after the other return expected data. 756 */ 757 TEST_F(UnsynchronizedWrite, MultipleRead) { 758 const size_t chunkSize = 100; 759 const size_t chunkNum = 5; 760 const size_t dataLen = chunkSize * chunkNum; 761 ASSERT_LE(dataLen, mNumMessagesMax); 762 uint8_t data[dataLen]; 763 initData(data, dataLen); 764 ASSERT_TRUE(mQueue->write(data, dataLen)); 765 uint8_t readData[dataLen] = {}; 766 for (size_t i = 0; i < chunkNum; i++) { 767 ASSERT_TRUE(mQueue->read(readData + i * chunkSize, chunkSize)); 768 } 769 ASSERT_EQ(0, memcmp(readData, data, dataLen)); 770 } 771 772 /* 773 * Verify that multiple writes one after the other happens correctly. 774 */ 775 TEST_F(UnsynchronizedWrite, MultipleWrite) { 776 const size_t chunkSize = 100; 777 const size_t chunkNum = 5; 778 const size_t dataLen = chunkSize * chunkNum; 779 ASSERT_LE(dataLen, mNumMessagesMax); 780 uint8_t data[dataLen]; 781 782 initData(data, dataLen); 783 for (size_t i = 0; i < chunkNum; i++) { 784 ASSERT_TRUE(mQueue->write(data + i * chunkSize, chunkSize)); 785 } 786 787 uint8_t readData[dataLen] = {}; 788 ASSERT_TRUE(mQueue->read(readData, dataLen)); 789 ASSERT_EQ(0, memcmp(readData, data, dataLen)); 790 } 791 792 /* 793 * Write enough messages into the FMQ to fill half of it 794 * and read back the same. 795 * Write mNumMessagesMax messages into the queue. This will cause a 796 * wrap around. Read and verify the data. 797 */ 798 TEST_F(UnsynchronizedWrite, ReadWriteWrapAround) { 799 size_t numMessages = mNumMessagesMax - 1; 800 std::vector<uint8_t> data(mNumMessagesMax); 801 std::vector<uint8_t> readData(mNumMessagesMax); 802 803 initData(&data[0], mNumMessagesMax); 804 ASSERT_TRUE(mQueue->write(&data[0], numMessages)); 805 ASSERT_TRUE(mQueue->read(&readData[0], numMessages)); 806 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax)); 807 ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax)); 808 ASSERT_EQ(data, readData); 809 } 810