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