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 <gtest/gtest.h>
18 #ifndef GTEST_IS_THREADSAFE
19 #error "GTest did not detect pthread library."
20 #endif
21
22 #include <fmq/MessageQueue.h>
23 #include <android/hardware/tests/msgq/1.0/ITestMsgQ.h>
24 #include <fmq/EventFlag.h>
25
26 // libutils:
27 using android::OK;
28 using android::sp;
29 using android::status_t;
30
31 // generated
32 using android::hardware::tests::msgq::V1_0::ITestMsgQ;
33
34 // libhidl
35 using android::hardware::kSynchronizedReadWrite;
36 using android::hardware::kUnsynchronizedWrite;
37 using android::hardware::MessageQueue;
38 using android::hardware::MQDescriptorSync;
39 using android::hardware::MQDescriptorUnsync;
40
41 typedef MessageQueue<uint16_t, kSynchronizedReadWrite> MessageQueueSync;
42 typedef MessageQueue<uint16_t, kUnsynchronizedWrite> MessageQueueUnsync;
43
44 class UnsynchronizedWriteClientMultiProcess : public ::testing::Test {
45 protected:
getQueue(MessageQueueUnsync ** fmq,sp<ITestMsgQ> & service,bool setupQueue)46 void getQueue(MessageQueueUnsync** fmq, sp<ITestMsgQ>& service, bool setupQueue) {
47 service = ITestMsgQ::getService();
48 ASSERT_NE(service, nullptr);
49 ASSERT_TRUE(service->isRemote());
50 service->getFmqUnsyncWrite(setupQueue,
51 [fmq](bool ret, const MQDescriptorUnsync<uint16_t>& in) {
52 ASSERT_TRUE(ret);
53 *fmq = new (std::nothrow) MessageQueueUnsync(in);
54 });
55 ASSERT_NE(*fmq, nullptr);
56 ASSERT_TRUE((*fmq)->isValid());
57 }
58 };
59
60 class SynchronizedReadWriteClient : public ::testing::Test {
61 protected:
TearDown()62 virtual void TearDown() {
63 delete mQueue;
64 }
65
SetUp()66 virtual void SetUp() {
67 mService = ITestMsgQ::getService();
68 ASSERT_NE(mService, nullptr);
69 ASSERT_TRUE(mService->isRemote());
70 mService->configureFmqSyncReadWrite([this](
71 bool ret, const MQDescriptorSync<uint16_t>& in) {
72 ASSERT_TRUE(ret);
73 mQueue = new (std::nothrow) MessageQueueSync(in);
74 });
75 ASSERT_NE(nullptr, mQueue);
76 ASSERT_TRUE(mQueue->isValid());
77 mNumMessagesMax = mQueue->getQuantumCount();
78 }
79
80 sp<ITestMsgQ> mService;
81 MessageQueueSync* mQueue = nullptr;
82 size_t mNumMessagesMax = 0;
83 };
84
85 class UnsynchronizedWriteClient : public ::testing::Test {
86 protected:
TearDown()87 virtual void TearDown() {
88 delete mQueue;
89 }
90
SetUp()91 virtual void SetUp() {
92 mService = ITestMsgQ::getService();
93 ASSERT_NE(mService, nullptr);
94 ASSERT_TRUE(mService->isRemote());
95 mService->getFmqUnsyncWrite(true /* configureFmq */,
96 [this](bool ret, const MQDescriptorUnsync<uint16_t>& in) {
97 ASSERT_TRUE(ret);
98 mQueue = new (std::nothrow) MessageQueueUnsync(in);
99 });
100 ASSERT_NE(nullptr, mQueue);
101 ASSERT_TRUE(mQueue->isValid());
102 mNumMessagesMax = mQueue->getQuantumCount();
103 }
104
105 sp<ITestMsgQ> mService;
106 MessageQueueUnsync* mQueue = nullptr;
107 size_t mNumMessagesMax = 0;
108 };
109
110 /*
111 * Utility function to verify data read from the fast message queue.
112 */
verifyData(uint16_t * data,size_t count)113 bool verifyData(uint16_t* data, size_t count) {
114 for (size_t i = 0; i < count; i++) {
115 if (data[i] != i) return false;
116 }
117 return true;
118 }
119
120 /*
121 * Utility function to initialize data to be written to the FMQ
122 */
initData(uint16_t * data,size_t count)123 inline void initData(uint16_t* data, size_t count) {
124 for (size_t i = 0; i < count; i++) {
125 data[i] = i;
126 }
127 }
128
129 /*
130 * Verify that for an unsynchronized flavor of FMQ, multiple readers
131 * can recover from a write overflow condition.
132 */
TEST_F(UnsynchronizedWriteClientMultiProcess,MultipleReadersAfterOverflow)133 TEST_F(UnsynchronizedWriteClientMultiProcess, MultipleReadersAfterOverflow) {
134 const size_t dataLen = 16;
135
136 pid_t pid;
137 /* creating first reader process */
138 if ((pid = fork()) == 0) {
139 sp<ITestMsgQ> testService;
140 MessageQueueUnsync* queue = nullptr;
141 getQueue(&queue, testService, true /* setupQueue */);
142
143 size_t numMessagesMax = queue->getQuantumCount();
144
145 // The following two writes will cause a write overflow.
146 auto ret = testService->requestWriteFmqUnsync(numMessagesMax);
147 ASSERT_TRUE(ret.isOk());
148 ASSERT_TRUE(ret);
149
150 ret = testService->requestWriteFmqUnsync(1);
151 ASSERT_TRUE(ret.isOk());
152 ASSERT_TRUE(ret);
153
154 // The following read should fail due to the overflow.
155 std::vector<uint16_t> readData(numMessagesMax);
156 ASSERT_FALSE(queue->read(&readData[0], numMessagesMax));
157
158 /*
159 * Request another write to verify that the reader can recover from the
160 * overflow condition.
161 */
162 ASSERT_LT(dataLen, numMessagesMax);
163 ret = testService->requestWriteFmqUnsync(dataLen);
164 ASSERT_TRUE(ret.isOk());
165 ASSERT_TRUE(ret);
166
167 // Verify that the read is successful.
168 ASSERT_TRUE(queue->read(&readData[0], dataLen));
169 ASSERT_TRUE(verifyData(&readData[0], dataLen));
170
171 delete queue;
172 exit(0);
173 }
174
175 ASSERT_GT(pid, 0 /* parent should see PID greater than 0 for a good fork */);
176
177 int status;
178 // wait for the first reader process to exit.
179 ASSERT_EQ(pid, waitpid(pid, &status, 0 /* options */));
180
181 // creating second reader process.
182 if ((pid = fork()) == 0) {
183 sp<ITestMsgQ> testService;
184 MessageQueueUnsync* queue = nullptr;
185
186 getQueue(&queue, testService, false /* setupQueue */);
187
188 // This read should fail due to the write overflow.
189 std::vector<uint16_t> readData(dataLen);
190 ASSERT_FALSE(queue->read(&readData[0], dataLen));
191
192 /*
193 * Request another write to verify that the process that recover from
194 * the overflow condition.
195 */
196 auto ret = testService->requestWriteFmqUnsync(dataLen);
197 ASSERT_TRUE(ret.isOk());
198 ASSERT_TRUE(ret);
199
200 // verify that the read is successful.
201 ASSERT_TRUE(queue->read(&readData[0], dataLen));
202 ASSERT_TRUE(verifyData(&readData[0], dataLen));
203
204 delete queue;
205 exit(0);
206 }
207
208 ASSERT_GT(pid, 0 /* parent should see PID greater than 0 for a good fork */);
209 ASSERT_EQ(pid, waitpid(pid, &status, 0 /* options */));
210 }
211
212 /*
213 * Test that basic blocking works using readBlocking()/writeBlocking() APIs
214 * using the EventFlag object owned by FMQ.
215 */
TEST_F(SynchronizedReadWriteClient,BlockingReadWrite1)216 TEST_F(SynchronizedReadWriteClient, BlockingReadWrite1) {
217 const size_t dataLen = 64;
218 uint16_t data[dataLen] = {0};
219
220 /*
221 * Request service to perform a blocking read. This call is oneway and will
222 * return immediately.
223 */
224 mService->requestBlockingRead(dataLen);
225 bool ret = mQueue->writeBlocking(data,
226 dataLen,
227 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
228 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
229 5000000000 /* timeOutNanos */);
230 ASSERT_TRUE(ret);
231 }
232
233 /*
234 * Test that basic blocking works using readBlocking()/writeBlocking() APIs
235 * using the EventFlag object owned by FMQ and using the default EventFlag
236 * notification bit mask.
237 */
TEST_F(SynchronizedReadWriteClient,BlockingReadWrite2)238 TEST_F(SynchronizedReadWriteClient, BlockingReadWrite2) {
239 const size_t dataLen = 64;
240 std::vector<uint16_t> data(mNumMessagesMax);
241
242 /*
243 * Request service to perform a blocking read using default EventFlag
244 * notification bit mask. This call is oneway and will
245 * return immediately.
246 */
247 mService->requestBlockingReadDefaultEventFlagBits(dataLen);
248
249 /* Cause a context switch to allow service to block */
250 sched_yield();
251
252 bool ret = mQueue->writeBlocking(&data[0],
253 dataLen);
254 ASSERT_TRUE(ret);
255
256 /*
257 * If the blocking read was successful, another write of size
258 * mNumMessagesMax will succeed.
259 */
260 ret = mQueue->writeBlocking(&data[0], mNumMessagesMax, 5000000000 /* timeOutNanos */);
261 ASSERT_TRUE(ret);
262 }
263
264 /*
265 * Test that repeated blocking reads and writes work using readBlocking()/writeBlocking() APIs
266 * using the EventFlag object owned by FMQ.
267 * Each write operation writes the same amount of data as a single read
268 * operation.
269 */
TEST_F(SynchronizedReadWriteClient,BlockingReadWriteRepeat1)270 TEST_F(SynchronizedReadWriteClient, BlockingReadWriteRepeat1) {
271 const size_t dataLen = 64;
272 uint16_t data[dataLen] = {0};
273
274 /*
275 * Request service to perform a blocking read. This call is oneway and will
276 * return immediately.
277 */
278 const size_t writeCount = 1024;
279 mService->requestBlockingReadRepeat(dataLen, writeCount);
280
281 for (size_t i = 0; i < writeCount; i++) {
282 bool ret = mQueue->writeBlocking(
283 data,
284 dataLen,
285 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
286 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
287 5000000000 /* timeOutNanos */);
288 ASSERT_TRUE(ret);
289 }
290 }
291
292 /*
293 * Test that repeated blocking reads and writes work using readBlocking()/writeBlocking() APIs
294 * using the EventFlag object owned by FMQ. Each read operation reads twice the
295 * amount of data as a single write.
296 *
297 */
TEST_F(SynchronizedReadWriteClient,BlockingReadWriteRepeat2)298 TEST_F(SynchronizedReadWriteClient, BlockingReadWriteRepeat2) {
299 const size_t dataLen = 64;
300 uint16_t data[dataLen] = {0};
301
302 /*
303 * Request service to perform a blocking read. This call is oneway and will
304 * return immediately.
305 */
306 const size_t writeCount = 1024;
307 mService->requestBlockingReadRepeat(dataLen*2, writeCount/2);
308
309 for (size_t i = 0; i < writeCount; i++) {
310 bool ret = mQueue->writeBlocking(
311 data,
312 dataLen,
313 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
314 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
315 5000000000 /* timeOutNanos */);
316 ASSERT_TRUE(ret);
317 }
318 }
319
320 /*
321 * Test that basic blocking works using readBlocking()/writeBlocking() APIs
322 * using the EventFlag object owned by FMQ. Each write operation writes twice
323 * the amount of data as a single read.
324 */
TEST_F(SynchronizedReadWriteClient,BlockingReadWriteRepeat3)325 TEST_F(SynchronizedReadWriteClient, BlockingReadWriteRepeat3) {
326 const size_t dataLen = 64;
327 uint16_t data[dataLen] = {0};
328
329 /*
330 * Request service to perform a blocking read. This call is oneway and will
331 * return immediately.
332 */
333 size_t writeCount = 1024;
334 mService->requestBlockingReadRepeat(dataLen/2, writeCount*2);
335
336 for (size_t i = 0; i < writeCount; i++) {
337 bool ret = mQueue->writeBlocking(
338 data,
339 dataLen,
340 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
341 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
342 5000000000 /* timeOutNanos */);
343 ASSERT_TRUE(ret);
344 }
345 }
346
347 /*
348 * Test that writeBlocking()/readBlocking() APIs do not block on
349 * attempts to write/read 0 messages and return true.
350 */
TEST_F(SynchronizedReadWriteClient,BlockingReadWriteZeroMessages)351 TEST_F(SynchronizedReadWriteClient, BlockingReadWriteZeroMessages) {
352 uint16_t data = 0;
353
354 /*
355 * Trigger a blocking write for zero messages with no timeout.
356 */
357 bool ret = mQueue->writeBlocking(
358 &data,
359 0,
360 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
361 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY));
362 ASSERT_TRUE(ret);
363
364 /*
365 * Trigger a blocking read for zero messages with no timeout.
366 */
367 ret = mQueue->readBlocking(&data,
368 0,
369 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
370 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY));
371 ASSERT_TRUE(ret);
372 }
373
374 /*
375 * Request mService to write a small number of messages
376 * to the FMQ. Read and verify data.
377 */
TEST_F(SynchronizedReadWriteClient,SmallInputReaderTest1)378 TEST_F(SynchronizedReadWriteClient, SmallInputReaderTest1) {
379 const size_t dataLen = 16;
380 ASSERT_LE(dataLen, mNumMessagesMax);
381 bool ret = mService->requestWriteFmqSync(dataLen);
382 ASSERT_TRUE(ret);
383 uint16_t readData[dataLen] = {};
384 ASSERT_TRUE(mQueue->read(readData, dataLen));
385 ASSERT_TRUE(verifyData(readData, dataLen));
386 }
387
388 /*
389 * Request mService to write a small number of messages
390 * to the FMQ. Read and verify each message using
391 * beginRead/Commit read APIs.
392 */
TEST_F(SynchronizedReadWriteClient,SmallInputReaderTest2)393 TEST_F(SynchronizedReadWriteClient, SmallInputReaderTest2) {
394 const size_t dataLen = 16;
395 ASSERT_LE(dataLen, mNumMessagesMax);
396 auto ret = mService->requestWriteFmqSync(dataLen);
397
398 ASSERT_TRUE(ret.isOk());
399 ASSERT_TRUE(ret);
400
401 MessageQueueSync::MemTransaction tx;
402 ASSERT_TRUE(mQueue->beginRead(dataLen, &tx));
403
404 auto first = tx.getFirstRegion();
405 auto second = tx.getSecondRegion();
406 size_t firstRegionLength = first.getLength();
407
408 for (size_t i = 0; i < dataLen; i++) {
409 if (i < firstRegionLength) {
410 ASSERT_EQ(i, *(first.getAddress() + i));
411 } else {
412 ASSERT_EQ(i, *(second.getAddress() + i - firstRegionLength));
413 }
414 }
415
416 ASSERT_TRUE(mQueue->commitRead(dataLen));
417 }
418
419 /*
420 * Write a small number of messages to FMQ. Request
421 * mService to read and verify that the write was succesful.
422 */
TEST_F(SynchronizedReadWriteClient,SmallInputWriterTest1)423 TEST_F(SynchronizedReadWriteClient, SmallInputWriterTest1) {
424 const size_t dataLen = 16;
425 ASSERT_LE(dataLen, mNumMessagesMax);
426 size_t originalCount = mQueue->availableToWrite();
427 uint16_t data[dataLen];
428 initData(data, dataLen);
429 ASSERT_TRUE(mQueue->write(data, dataLen));
430 bool ret = mService->requestReadFmqSync(dataLen);
431 ASSERT_TRUE(ret);
432 size_t availableCount = mQueue->availableToWrite();
433 ASSERT_EQ(originalCount, availableCount);
434 }
435
436 /*
437 * Write a small number of messages to FMQ using the beginWrite()/CommitWrite()
438 * APIs. Request mService to read and verify that the write was succesful.
439 */
TEST_F(SynchronizedReadWriteClient,SmallInputWriterTest2)440 TEST_F(SynchronizedReadWriteClient, SmallInputWriterTest2) {
441 const size_t dataLen = 16;
442 ASSERT_LE(dataLen, mNumMessagesMax);
443 size_t originalCount = mQueue->availableToWrite();
444 uint16_t data[dataLen];
445 initData(data, dataLen);
446
447 MessageQueueSync::MemTransaction tx;
448 ASSERT_TRUE(mQueue->beginWrite(dataLen, &tx));
449
450 auto first = tx.getFirstRegion();
451 auto second = tx.getSecondRegion();
452
453 size_t firstRegionLength = first.getLength();
454 uint16_t* firstBaseAddress = first.getAddress();
455 uint16_t* secondBaseAddress = second.getAddress();
456
457 for (size_t i = 0; i < dataLen; i++) {
458 if (i < firstRegionLength) {
459 *(firstBaseAddress + i) = i;
460 } else {
461 *(secondBaseAddress + i - firstRegionLength) = i;
462 }
463 }
464
465 ASSERT_TRUE(mQueue->commitWrite(dataLen));
466
467 auto ret = mService->requestReadFmqSync(dataLen);
468 ASSERT_TRUE(ret.isOk());
469 ASSERT_TRUE(ret);
470 size_t availableCount = mQueue->availableToWrite();
471 ASSERT_EQ(originalCount, availableCount);
472 }
473
474 /*
475 * Verify that the FMQ is empty and read fails when it is empty.
476 */
TEST_F(SynchronizedReadWriteClient,ReadWhenEmpty)477 TEST_F(SynchronizedReadWriteClient, ReadWhenEmpty) {
478 ASSERT_EQ(0UL, mQueue->availableToRead());
479 const size_t numMessages = 2;
480 ASSERT_LE(numMessages, mNumMessagesMax);
481 uint16_t readData[numMessages];
482 ASSERT_FALSE(mQueue->read(readData, numMessages));
483 }
484
485 /*
486 * Verify FMQ is empty.
487 * Write enough messages to fill it.
488 * Verify availableToWrite() method returns is zero.
489 * Try writing another message and verify that
490 * the attempted write was unsuccesful. Request mService
491 * to read and verify the messages in the FMQ.
492 */
493
TEST_F(SynchronizedReadWriteClient,WriteWhenFull)494 TEST_F(SynchronizedReadWriteClient, WriteWhenFull) {
495 std::vector<uint16_t> data(mNumMessagesMax);
496 initData(&data[0], mNumMessagesMax);
497 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
498 ASSERT_EQ(0UL, mQueue->availableToWrite());
499 ASSERT_FALSE(mQueue->write(&data[0], 1));
500 bool ret = mService->requestReadFmqSync(mNumMessagesMax);
501 ASSERT_TRUE(ret);
502 }
503
504 /*
505 * Verify FMQ is empty.
506 * Request mService to write data equal to queue size.
507 * Read and verify data in mQueue.
508 */
TEST_F(SynchronizedReadWriteClient,LargeInputTest1)509 TEST_F(SynchronizedReadWriteClient, LargeInputTest1) {
510 bool ret = mService->requestWriteFmqSync(mNumMessagesMax);
511 ASSERT_TRUE(ret);
512 std::vector<uint16_t> readData(mNumMessagesMax);
513 ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax));
514 ASSERT_TRUE(verifyData(&readData[0], mNumMessagesMax));
515 }
516
517 /*
518 * Request mService to write more than maximum number of messages to the FMQ.
519 * Verify that the write fails. Verify that availableToRead() method
520 * still returns 0 and verify that attempt to read fails.
521 */
TEST_F(SynchronizedReadWriteClient,LargeInputTest2)522 TEST_F(SynchronizedReadWriteClient, LargeInputTest2) {
523 ASSERT_EQ(0UL, mQueue->availableToRead());
524 const size_t numMessages = 2048;
525 ASSERT_GT(numMessages, mNumMessagesMax);
526 bool ret = mService->requestWriteFmqSync(numMessages);
527 ASSERT_FALSE(ret);
528 uint16_t readData;
529 ASSERT_EQ(0UL, mQueue->availableToRead());
530 ASSERT_FALSE(mQueue->read(&readData, 1));
531 }
532
533 /*
534 * Write until FMQ is full.
535 * Verify that the number of messages available to write
536 * is equal to mNumMessagesMax.
537 * Verify that another write attempt fails.
538 * Request mService to read. Verify read count.
539 */
540
TEST_F(SynchronizedReadWriteClient,LargeInputTest3)541 TEST_F(SynchronizedReadWriteClient, LargeInputTest3) {
542 std::vector<uint16_t> data(mNumMessagesMax);
543 initData(&data[0], mNumMessagesMax);
544 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
545 ASSERT_EQ(0UL, mQueue->availableToWrite());
546 ASSERT_FALSE(mQueue->write(&data[0], 1));
547
548 bool ret = mService->requestReadFmqSync(mNumMessagesMax);
549 ASSERT_TRUE(ret);
550 }
551
552 /*
553 * Confirm that the FMQ is empty. Request mService to write to FMQ.
554 * Do multiple reads to empty FMQ and verify data.
555 */
TEST_F(SynchronizedReadWriteClient,MultipleRead)556 TEST_F(SynchronizedReadWriteClient, MultipleRead) {
557 const size_t chunkSize = 100;
558 const size_t chunkNum = 5;
559 const size_t numMessages = chunkSize * chunkNum;
560 ASSERT_LE(numMessages, mNumMessagesMax);
561 size_t availableToRead = mQueue->availableToRead();
562 size_t expectedCount = 0;
563 ASSERT_EQ(expectedCount, availableToRead);
564 bool ret = mService->requestWriteFmqSync(numMessages);
565 ASSERT_TRUE(ret);
566 uint16_t readData[numMessages] = {};
567 for (size_t i = 0; i < chunkNum; i++) {
568 ASSERT_TRUE(mQueue->read(readData + i * chunkSize, chunkSize));
569 }
570 ASSERT_TRUE(verifyData(readData, numMessages));
571 }
572
573 /*
574 * Write to FMQ in bursts.
575 * Request mService to read data. Verify the read was successful.
576 */
TEST_F(SynchronizedReadWriteClient,MultipleWrite)577 TEST_F(SynchronizedReadWriteClient, MultipleWrite) {
578 const size_t chunkSize = 100;
579 const size_t chunkNum = 5;
580 const size_t numMessages = chunkSize * chunkNum;
581 ASSERT_LE(numMessages, mNumMessagesMax);
582 uint16_t data[numMessages];
583 initData(&data[0], numMessages);
584
585 for (size_t i = 0; i < chunkNum; i++) {
586 ASSERT_TRUE(mQueue->write(data + i * chunkSize, chunkSize));
587 }
588 bool ret = mService->requestReadFmqSync(numMessages);
589 ASSERT_TRUE(ret);
590 }
591
592 /*
593 * Write enough messages into the FMQ to fill half of it.
594 * Request mService to read back the same.
595 * Write mNumMessagesMax messages into the queue. This should cause a
596 * wrap around. Request mService to read and verify the data.
597 */
TEST_F(SynchronizedReadWriteClient,ReadWriteWrapAround)598 TEST_F(SynchronizedReadWriteClient, ReadWriteWrapAround) {
599 size_t numMessages = mNumMessagesMax / 2;
600 std::vector<uint16_t> data(mNumMessagesMax);
601 initData(&data[0], mNumMessagesMax);
602 ASSERT_TRUE(mQueue->write(&data[0], numMessages));
603 bool ret = mService->requestReadFmqSync(numMessages);
604 ASSERT_TRUE(ret);
605 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
606 ret = mService->requestReadFmqSync(mNumMessagesMax);
607 ASSERT_TRUE(ret);
608 }
609
610 /*
611 * Use beginWrite/commitWrite/getSlot APIs to test wrap arounds are handled
612 * correctly.
613 * Write enough messages into the FMQ to fill half of it
614 * and read back the same.
615 * Write mNumMessagesMax messages into the queue. This will cause a
616 * wrap around. Read and verify the data.
617 */
TEST_F(SynchronizedReadWriteClient,ReadWriteWrapAround2)618 TEST_F(SynchronizedReadWriteClient, ReadWriteWrapAround2) {
619 size_t numMessages = mNumMessagesMax / 2;
620 std::vector<uint16_t> data(mNumMessagesMax);
621 initData(&data[0], mNumMessagesMax);
622 ASSERT_TRUE(mQueue->write(&data[0], numMessages));
623 auto ret = mService->requestReadFmqSync(numMessages);
624
625 ASSERT_TRUE(ret.isOk());
626 ASSERT_TRUE(ret);
627
628 /*
629 * The next write and read will have to deal with with wrap arounds.
630 */
631 MessageQueueSync::MemTransaction tx;
632 ASSERT_TRUE(mQueue->beginWrite(mNumMessagesMax, &tx));
633
634 ASSERT_EQ(tx.getFirstRegion().getLength() + tx.getSecondRegion().getLength(), mNumMessagesMax);
635
636 for (size_t i = 0; i < mNumMessagesMax; i++) {
637 uint16_t* ptr = tx.getSlot(i);
638 *ptr = data[i];
639 }
640
641 ASSERT_TRUE(mQueue->commitWrite(mNumMessagesMax));
642
643 ret = mService->requestReadFmqSync(mNumMessagesMax);
644
645 ASSERT_TRUE(ret.isOk());
646 ASSERT_TRUE(ret);
647 }
648
649 /*
650 * Request mService to write a small number of messages
651 * to the FMQ. Read and verify data.
652 */
TEST_F(UnsynchronizedWriteClient,SmallInputReaderTest1)653 TEST_F(UnsynchronizedWriteClient, SmallInputReaderTest1) {
654 const size_t dataLen = 16;
655 ASSERT_LE(dataLen, mNumMessagesMax);
656 bool ret = mService->requestWriteFmqUnsync(dataLen);
657 ASSERT_TRUE(ret);
658 uint16_t readData[dataLen] = {};
659 ASSERT_TRUE(mQueue->read(readData, dataLen));
660 ASSERT_TRUE(verifyData(readData, dataLen));
661 }
662
663 /*
664 * Write a small number of messages to FMQ. Request
665 * mService to read and verify that the write was succesful.
666 */
TEST_F(UnsynchronizedWriteClient,SmallInputWriterTest1)667 TEST_F(UnsynchronizedWriteClient, SmallInputWriterTest1) {
668 const size_t dataLen = 16;
669 ASSERT_LE(dataLen, mNumMessagesMax);
670 uint16_t data[dataLen];
671 initData(data, dataLen);
672 ASSERT_TRUE(mQueue->write(data, dataLen));
673 bool ret = mService->requestReadFmqUnsync(dataLen);
674 ASSERT_TRUE(ret);
675 }
676
677 /*
678 * Verify that the FMQ is empty and read fails when it is empty.
679 */
TEST_F(UnsynchronizedWriteClient,ReadWhenEmpty)680 TEST_F(UnsynchronizedWriteClient, ReadWhenEmpty) {
681 ASSERT_EQ(0UL, mQueue->availableToRead());
682 const size_t numMessages = 2;
683 ASSERT_LE(numMessages, mNumMessagesMax);
684 uint16_t readData[numMessages];
685 ASSERT_FALSE(mQueue->read(readData, numMessages));
686 }
687
688 /*
689 * Verify FMQ is empty.
690 * Write enough messages to fill it.
691 * Verify availableToWrite() method returns is zero.
692 * Try writing another message and verify that
693 * the attempted write was successful. Request mService
694 * to read the messages in the FMQ and verify that it is unsuccesful.
695 */
696
TEST_F(UnsynchronizedWriteClient,WriteWhenFull)697 TEST_F(UnsynchronizedWriteClient, WriteWhenFull) {
698 std::vector<uint16_t> data(mNumMessagesMax);
699 initData(&data[0], mNumMessagesMax);
700 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
701 ASSERT_EQ(0UL, mQueue->availableToWrite());
702 ASSERT_TRUE(mQueue->write(&data[0], 1));
703 bool ret = mService->requestReadFmqUnsync(mNumMessagesMax);
704 ASSERT_FALSE(ret);
705 }
706
707 /*
708 * Verify FMQ is empty.
709 * Request mService to write data equal to queue size.
710 * Read and verify data in mQueue.
711 */
TEST_F(UnsynchronizedWriteClient,LargeInputTest1)712 TEST_F(UnsynchronizedWriteClient, LargeInputTest1) {
713 bool ret = mService->requestWriteFmqUnsync(mNumMessagesMax);
714 ASSERT_TRUE(ret);
715 std::vector<uint16_t> data(mNumMessagesMax);
716 ASSERT_TRUE(mQueue->read(&data[0], mNumMessagesMax));
717 ASSERT_TRUE(verifyData(&data[0], mNumMessagesMax));
718 }
719
720 /*
721 * Request mService to write more than maximum number of messages to the FMQ.
722 * Verify that the write fails. Verify that availableToRead() method
723 * still returns 0 and verify that attempt to read fails.
724 */
TEST_F(UnsynchronizedWriteClient,LargeInputTest2)725 TEST_F(UnsynchronizedWriteClient, LargeInputTest2) {
726 ASSERT_EQ(0UL, mQueue->availableToRead());
727 const size_t numMessages = mNumMessagesMax + 1;
728 bool ret = mService->requestWriteFmqUnsync(numMessages);
729 ASSERT_FALSE(ret);
730 uint16_t readData;
731 ASSERT_EQ(0UL, mQueue->availableToRead());
732 ASSERT_FALSE(mQueue->read(&readData, 1));
733 }
734
735 /*
736 * Write until FMQ is full.
737 * Verify that the number of messages available to write
738 * is equal to mNumMessagesMax.
739 * Verify that another write attempt is succesful.
740 * Request mService to read. Verify that read is unsuccessful.
741 * Perform another write and verify that the read is succesful
742 * to check if the reader process can recover from the error condition.
743 */
TEST_F(UnsynchronizedWriteClient,LargeInputTest3)744 TEST_F(UnsynchronizedWriteClient, LargeInputTest3) {
745 std::vector<uint16_t> data(mNumMessagesMax);
746 initData(&data[0], mNumMessagesMax);
747 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
748 ASSERT_EQ(0UL, mQueue->availableToWrite());
749 ASSERT_TRUE(mQueue->write(&data[0], 1));
750
751 bool ret = mService->requestReadFmqUnsync(mNumMessagesMax);
752 ASSERT_FALSE(ret);
753 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
754
755 ret = mService->requestReadFmqUnsync(mNumMessagesMax);
756 ASSERT_TRUE(ret);
757 }
758
759 /*
760 * Confirm that the FMQ is empty. Request mService to write to FMQ.
761 * Do multiple reads to empty FMQ and verify data.
762 */
TEST_F(UnsynchronizedWriteClient,MultipleRead)763 TEST_F(UnsynchronizedWriteClient, MultipleRead) {
764 const size_t chunkSize = 100;
765 const size_t chunkNum = 5;
766 const size_t numMessages = chunkSize * chunkNum;
767 ASSERT_LE(numMessages, mNumMessagesMax);
768 size_t availableToRead = mQueue->availableToRead();
769 size_t expectedCount = 0;
770 ASSERT_EQ(expectedCount, availableToRead);
771 bool ret = mService->requestWriteFmqUnsync(numMessages);
772 ASSERT_TRUE(ret);
773 uint16_t readData[numMessages] = {};
774 for (size_t i = 0; i < chunkNum; i++) {
775 ASSERT_TRUE(mQueue->read(readData + i * chunkSize, chunkSize));
776 }
777 ASSERT_TRUE(verifyData(readData, numMessages));
778 }
779
780 /*
781 * Write to FMQ in bursts.
782 * Request mService to read data, verify that it was successful.
783 */
TEST_F(UnsynchronizedWriteClient,MultipleWrite)784 TEST_F(UnsynchronizedWriteClient, MultipleWrite) {
785 const size_t chunkSize = 100;
786 const size_t chunkNum = 5;
787 const size_t numMessages = chunkSize * chunkNum;
788 ASSERT_LE(numMessages, mNumMessagesMax);
789 uint16_t data[numMessages];
790 initData(data, numMessages);
791 for (size_t i = 0; i < chunkNum; i++) {
792 ASSERT_TRUE(mQueue->write(data + i * chunkSize, chunkSize));
793 }
794 bool ret = mService->requestReadFmqUnsync(numMessages);
795 ASSERT_TRUE(ret);
796 }
797
798 /*
799 * Write enough messages into the FMQ to fill half of it.
800 * Request mService to read back the same.
801 * Write mNumMessagesMax messages into the queue. This should cause a
802 * wrap around. Request mService to read and verify the data.
803 */
TEST_F(UnsynchronizedWriteClient,ReadWriteWrapAround)804 TEST_F(UnsynchronizedWriteClient, ReadWriteWrapAround) {
805 size_t numMessages = mNumMessagesMax / 2;
806 std::vector<uint16_t> data(mNumMessagesMax);
807 initData(&data[0], mNumMessagesMax);
808 ASSERT_TRUE(mQueue->write(&data[0], numMessages));
809 bool ret = mService->requestReadFmqUnsync(numMessages);
810 ASSERT_TRUE(ret);
811 ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
812 ret = mService->requestReadFmqUnsync(mNumMessagesMax);
813 ASSERT_TRUE(ret);
814 }
815
816 /*
817 * Request mService to write a small number of messages
818 * to the FMQ. Read and verify data from two threads configured
819 * as readers to the FMQ.
820 */
TEST_F(UnsynchronizedWriteClient,SmallInputMultipleReaderTest)821 TEST_F(UnsynchronizedWriteClient, SmallInputMultipleReaderTest) {
822 auto desc = mQueue->getDesc();
823 std::unique_ptr<MessageQueue<uint16_t, kUnsynchronizedWrite>> mQueue2(
824 new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite>(*desc));
825 ASSERT_NE(nullptr, mQueue2.get());
826
827 const size_t dataLen = 16;
828 ASSERT_LE(dataLen, mNumMessagesMax);
829
830 bool ret = mService->requestWriteFmqUnsync(dataLen);
831 ASSERT_TRUE(ret);
832
833 pid_t pid;
834 if ((pid = fork()) == 0) {
835 /* child process */
836 uint16_t readData[dataLen] = {};
837 ASSERT_TRUE(mQueue2->read(readData, dataLen));
838 ASSERT_TRUE(verifyData(readData, dataLen));
839 exit(0);
840 } else {
841 ASSERT_GT(pid,
842 0 /* parent should see PID greater than 0 for a good fork */);
843 uint16_t readData[dataLen] = {};
844 ASSERT_TRUE(mQueue->read(readData, dataLen));
845 ASSERT_TRUE(verifyData(readData, dataLen));
846 }
847 }
848
849 /*
850 * Request mService to write into the FMQ until it is full.
851 * Request mService to do another write and verify it is successful.
852 * Use two reader processes to read and verify that both fail.
853 */
TEST_F(UnsynchronizedWriteClient,OverflowNotificationTest)854 TEST_F(UnsynchronizedWriteClient, OverflowNotificationTest) {
855 auto desc = mQueue->getDesc();
856 std::unique_ptr<MessageQueue<uint16_t, kUnsynchronizedWrite>> mQueue2(
857 new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite>(*desc));
858 ASSERT_NE(nullptr, mQueue2.get());
859
860 bool ret = mService->requestWriteFmqUnsync(mNumMessagesMax);
861 ASSERT_TRUE(ret);
862 ret = mService->requestWriteFmqUnsync(1);
863 ASSERT_TRUE(ret);
864
865 pid_t pid;
866 if ((pid = fork()) == 0) {
867 /* child process */
868 std::vector<uint16_t> readData(mNumMessagesMax);
869 ASSERT_FALSE(mQueue2->read(&readData[0], mNumMessagesMax));
870 exit(0);
871 } else {
872 ASSERT_GT(pid, 0/* parent should see PID greater than 0 for a good fork */);
873 std::vector<uint16_t> readData(mNumMessagesMax);
874 ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax));
875 }
876 }
877