xref: /aosp_15_r20/system/libfmq/tests/msgq_test_client.cpp (revision be431cd81a9a2349eaea34eb56fcf6d1608da596)
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 <aidl/android/fmq/test/FixedParcelable.h>
23 #include <aidl/android/fmq/test/FixedUnion.h>
24 #include <aidl/android/fmq/test/ITestAidlMsgQ.h>
25 #include <android-base/logging.h>
26 #include <android/binder_manager.h>
27 #include <android/binder_process.h>
28 #include <android/fmq/test/FixedParcelable.h>
29 #include <android/fmq/test/FixedUnion.h>
30 #include <android/fmq/test/ITestAidlMsgQ.h>
31 #include <android/hardware/tests/msgq/1.0/ITestMsgQ.h>
32 #include <fmq/AidlMessageQueue.h>
33 #include <fmq/AidlMessageQueueCpp.h>
34 #include <fmq/EventFlag.h>
35 #include <fmq/MessageQueue.h>
36 #include <hidl/ServiceManagement.h>
37 
38 #include <binder/IServiceManager.h>
39 
40 // libutils:
41 using android::OK;
42 using android::sp;
43 using android::status_t;
44 
45 // generated
46 using ::aidl::android::fmq::test::EventFlagBits;
47 using ::aidl::android::fmq::test::FixedParcelable;
48 using ::aidl::android::fmq::test::FixedUnion;
49 using ::aidl::android::fmq::test::ITestAidlMsgQ;
50 
51 using cppEventFlagBits = ::android::fmq::test::EventFlagBits;
52 using cppFixedParcelable = android::fmq::test::FixedParcelable;
53 using cppFixedUnion = android::fmq::test::FixedUnion;
54 using cppITestAidlMsgQ = ::android::fmq::test::ITestAidlMsgQ;
55 
56 using android::hardware::tests::msgq::V1_0::ITestMsgQ;
57 static_assert(static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL) ==
58                       static_cast<uint32_t>(EventFlagBits::FMQ_NOT_FULL),
59               "The AIDL and HIDL test interfaces must use the same values!");
60 static_assert(static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY) ==
61                       static_cast<uint32_t>(EventFlagBits::FMQ_NOT_EMPTY),
62               "The AIDL and HIDL test interfaces must use the same values!");
63 
64 // libhidl
65 using android::hardware::isHidlSupported;
66 using android::hardware::kSynchronizedReadWrite;
67 using android::hardware::kUnsynchronizedWrite;
68 using android::hardware::MessageQueue;
69 using android::hardware::MQDescriptorSync;
70 using android::hardware::MQDescriptorUnsync;
71 using android::hardware::details::waitForHwService;
72 
73 using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
74 using aidl::android::hardware::common::fmq::UnsynchronizedWrite;
75 using cppSynchronizedReadWrite = ::android::hardware::common::fmq::SynchronizedReadWrite;
76 using cppUnSynchronizedWrite = android::hardware::common::fmq::UnsynchronizedWrite;
77 using android::hardware::kSynchronizedReadWrite;
78 using android::hardware::kUnsynchronizedWrite;
79 
80 typedef android::AidlMessageQueue<int32_t, SynchronizedReadWrite> AidlMessageQueueSync;
81 typedef android::AidlMessageQueue<int32_t, UnsynchronizedWrite> AidlMessageQueueUnsync;
82 
83 typedef android::AidlMessageQueueCpp<int32_t, cppSynchronizedReadWrite> cppAidlMessageQueueSync;
84 typedef android::AidlMessageQueueCpp<int32_t, cppUnSynchronizedWrite> cppAidlMessageQueueUnsync;
85 
86 typedef android::hardware::MessageQueue<int32_t, kSynchronizedReadWrite> MessageQueueSync;
87 typedef android::hardware::MessageQueue<int32_t, kUnsynchronizedWrite> MessageQueueUnsync;
88 static const size_t kPageSize = getpagesize();
89 static const size_t kNumElementsInSyncQueue = (kPageSize - 16) / sizeof(int32_t);
90 
91 enum class SetupType {
92     SINGLE_FD,
93     DOUBLE_FD,
94 };
95 
96 template <typename T, SetupType setupType>
97 class TestParamTypes {
98   public:
99     typedef T MQType;
100     static constexpr bool UserFd = setupType == SetupType::DOUBLE_FD;
101 };
102 
103 // Run everything on both the AIDL and HIDL versions with one and two FDs
104 typedef ::testing::Types<TestParamTypes<AidlMessageQueueSync, SetupType::SINGLE_FD>,
105                          TestParamTypes<cppAidlMessageQueueSync, SetupType::SINGLE_FD>,
106                          TestParamTypes<MessageQueueSync, SetupType::SINGLE_FD>,
107                          TestParamTypes<AidlMessageQueueSync, SetupType::DOUBLE_FD>,
108                          TestParamTypes<cppAidlMessageQueueSync, SetupType::DOUBLE_FD>,
109                          TestParamTypes<MessageQueueSync, SetupType::DOUBLE_FD>>
110         SyncTypes;
111 typedef ::testing::Types<TestParamTypes<AidlMessageQueueUnsync, SetupType::SINGLE_FD>,
112                          TestParamTypes<cppAidlMessageQueueUnsync, SetupType::SINGLE_FD>,
113                          TestParamTypes<MessageQueueUnsync, SetupType::SINGLE_FD>,
114                          TestParamTypes<AidlMessageQueueUnsync, SetupType::DOUBLE_FD>,
115                          TestParamTypes<cppAidlMessageQueueUnsync, SetupType::DOUBLE_FD>,
116                          TestParamTypes<MessageQueueUnsync, SetupType::DOUBLE_FD>>
117         UnsyncTypes;
118 
119 template <typename T>
120 class ClientSyncTestBase : public ::testing::Test {};
121 
122 // Specialize for AIDL
123 template <>
124 class ClientSyncTestBase<AidlMessageQueueSync> : public ::testing::Test {
125   protected:
waitGetTestService()126     static std::shared_ptr<ITestAidlMsgQ> waitGetTestService() {
127         const std::string instance = std::string() + ITestAidlMsgQ::descriptor + "/default";
128         ndk::SpAIBinder binder(AServiceManager_getService(instance.c_str()));
129         CHECK(nullptr != binder);
130         auto ret = ITestAidlMsgQ::fromBinder(binder);
131         CHECK(ret->isRemote() == true);
132         return ret;
133     }
configureFmqSyncReadWrite(AidlMessageQueueSync * mq)134     bool configureFmqSyncReadWrite(AidlMessageQueueSync* mq) {
135         bool result = false;
136         auto ret = mService->configureFmqSyncReadWrite(mq->dupeDesc(), &result);
137         return result && ret.isOk();
138     }
requestReadFmqSync(size_t dataLen)139     bool requestReadFmqSync(size_t dataLen) {
140         bool result = false;
141         auto ret = mService->requestReadFmqSync(dataLen, &result);
142         return result && ret.isOk();
143     }
requestWriteFmqSync(size_t dataLen)144     bool requestWriteFmqSync(size_t dataLen) {
145         bool result = false;
146         auto ret = mService->requestWriteFmqSync(dataLen, &result);
147         return result && ret.isOk();
148     }
149 
150     std::shared_ptr<ITestAidlMsgQ> mService;
151 };
152 
153 // Specialize for AIDL cpp backend
154 template <>
155 class ClientSyncTestBase<cppAidlMessageQueueSync> : public ::testing::Test {
156   protected:
waitGetTestService()157     static sp<cppITestAidlMsgQ> waitGetTestService() {
158         const std::string instance = std::string() + ITestAidlMsgQ::descriptor + "/default";
159         const android::String16 instanceString16(instance.c_str());
160         sp<cppITestAidlMsgQ> binder;
161         status_t err = getService(instanceString16, &binder);
162         if (err != OK) {
163             return nullptr;
164         }
165         CHECK(nullptr != binder);
166         return binder;
167     }
configureFmqSyncReadWrite(cppAidlMessageQueueSync * mq)168     bool configureFmqSyncReadWrite(cppAidlMessageQueueSync* mq) {
169         bool result = false;
170         auto ret = mService->configureFmqSyncReadWrite(mq->dupeDesc(), &result);
171         return result && ret.isOk();
172     }
requestReadFmqSync(size_t dataLen)173     bool requestReadFmqSync(size_t dataLen) {
174         bool result = false;
175         auto ret = mService->requestReadFmqSync(dataLen, &result);
176         return result && ret.isOk();
177     }
requestWriteFmqSync(size_t dataLen)178     bool requestWriteFmqSync(size_t dataLen) {
179         bool result = false;
180         auto ret = mService->requestWriteFmqSync(dataLen, &result);
181         return result && ret.isOk();
182     }
183 
184     sp<cppITestAidlMsgQ> mService;
185 };
186 
187 // Specialize for HIDL
188 template <>
189 class ClientSyncTestBase<MessageQueueSync> : public ::testing::Test {
190   protected:
waitGetTestService()191     static sp<ITestMsgQ> waitGetTestService() {
192         if (isHidlSupported()) {
193             android::hardware::details::setTrebleTestingOverride(true);
194             // waitForHwService is required because ITestMsgQ is not in manifest.xml.
195             // "Real" HALs shouldn't be doing this.
196             waitForHwService(ITestMsgQ::descriptor, "default");
197             sp<ITestMsgQ> service = ITestMsgQ::getService();
198             CHECK(nullptr != service);
199             CHECK(service->isRemote() == true);
200             return service;
201         } else {
202             return nullptr;
203         }
204     }
configureFmqSyncReadWrite(MessageQueueSync * mq)205     bool configureFmqSyncReadWrite(MessageQueueSync* mq) {
206         auto ret = mService->configureFmqSyncReadWrite(*mq->getDesc());
207         return ret && ret.isOk();
208     }
requestReadFmqSync(size_t dataLen)209     bool requestReadFmqSync(size_t dataLen) {
210         auto ret = mService->requestReadFmqSync(dataLen);
211         return ret && ret.isOk();
212     }
requestWriteFmqSync(size_t dataLen)213     bool requestWriteFmqSync(size_t dataLen) {
214         auto ret = mService->requestWriteFmqSync(dataLen);
215         return ret && ret.isOk();
216     }
217 
218     sp<ITestMsgQ> mService;
219 };
220 
221 template <typename T>
222 class ClientUnsyncTestBase : public ::testing::Test {};
223 
224 // Specialize for AIDL
225 template <>
226 class ClientUnsyncTestBase<AidlMessageQueueUnsync> : public ::testing::Test {
227   protected:
waitGetTestService()228     static std::shared_ptr<ITestAidlMsgQ> waitGetTestService() {
229         const std::string instance = std::string() + ITestAidlMsgQ::descriptor + "/default";
230         ndk::SpAIBinder binder(AServiceManager_getService(instance.c_str()));
231         CHECK(nullptr != binder);
232         auto ret = ITestAidlMsgQ::fromBinder(binder);
233         CHECK(ret->isRemote() == true);
234         return ret;
235     }
getFmqUnsyncWrite(bool configureFmq,bool userFd,std::shared_ptr<ITestAidlMsgQ> service,AidlMessageQueueUnsync ** queue)236     bool getFmqUnsyncWrite(bool configureFmq, bool userFd, std::shared_ptr<ITestAidlMsgQ> service,
237                            AidlMessageQueueUnsync** queue) {
238         bool result = false;
239         aidl::android::hardware::common::fmq::MQDescriptor<int32_t, UnsynchronizedWrite> desc;
240         auto ret = service->getFmqUnsyncWrite(configureFmq, userFd, &desc, &result);
241         *queue = new (std::nothrow) AidlMessageQueueUnsync(desc, false);
242         return result && ret.isOk();
243     }
244 
getQueue(AidlMessageQueueUnsync ** fmq,bool setupQueue,bool userFd)245     std::shared_ptr<ITestAidlMsgQ> getQueue(AidlMessageQueueUnsync** fmq, bool setupQueue,
246                                             bool userFd) {
247         std::shared_ptr<ITestAidlMsgQ> service = waitGetTestService();
248         if (service == nullptr) return nullptr;
249         getFmqUnsyncWrite(setupQueue, userFd, service, fmq);
250         return service;
251     }
252 
requestReadFmqUnsync(size_t dataLen,std::shared_ptr<ITestAidlMsgQ> service)253     bool requestReadFmqUnsync(size_t dataLen, std::shared_ptr<ITestAidlMsgQ> service) {
254         bool result = false;
255         auto ret = service->requestReadFmqUnsync(dataLen, &result);
256         return result && ret.isOk();
257     }
requestWriteFmqUnsync(size_t dataLen,std::shared_ptr<ITestAidlMsgQ> service)258     bool requestWriteFmqUnsync(size_t dataLen, std::shared_ptr<ITestAidlMsgQ> service) {
259         bool result = false;
260         auto ret = service->requestWriteFmqUnsync(dataLen, &result);
261         return result && ret.isOk();
262     }
newQueue()263     AidlMessageQueueUnsync* newQueue() {
264         if (mQueue->isValid())
265             return new (std::nothrow) AidlMessageQueueUnsync(mQueue->dupeDesc(), false);
266         else
267             return nullptr;
268     }
269 
270     std::shared_ptr<ITestAidlMsgQ> mService;
271     AidlMessageQueueUnsync* mQueue = nullptr;
272 };
273 
274 // Specialize for AIDL cpp backend
275 template <>
276 class ClientUnsyncTestBase<cppAidlMessageQueueUnsync> : public ::testing::Test {
277   protected:
waitGetTestService()278     static sp<cppITestAidlMsgQ> waitGetTestService() {
279         const std::string instance = std::string() + ITestAidlMsgQ::descriptor + "/default";
280         const android::String16 instanceString16(instance.c_str());
281         sp<cppITestAidlMsgQ> binder;
282         status_t err = getService(instanceString16, &binder);
283         if (err != OK) {
284             return nullptr;
285         }
286         CHECK(nullptr != binder);
287         return binder;
288     }
getFmqUnsyncWrite(bool configureFmq,bool userFd,sp<cppITestAidlMsgQ> service,cppAidlMessageQueueUnsync ** queue)289     bool getFmqUnsyncWrite(bool configureFmq, bool userFd, sp<cppITestAidlMsgQ> service,
290                            cppAidlMessageQueueUnsync** queue) {
291         bool result = false;
292         android::hardware::common::fmq::MQDescriptor<int32_t, cppUnSynchronizedWrite> desc;
293         auto ret = service->getFmqUnsyncWrite(configureFmq, userFd, &desc, &result);
294         *queue = new (std::nothrow) cppAidlMessageQueueUnsync(desc, false);
295         return result && ret.isOk();
296     }
297 
getQueue(cppAidlMessageQueueUnsync ** fmq,bool setupQueue,bool userFd)298     sp<cppITestAidlMsgQ> getQueue(cppAidlMessageQueueUnsync** fmq, bool setupQueue, bool userFd) {
299         sp<cppITestAidlMsgQ> service = waitGetTestService();
300         if (service == nullptr) return nullptr;
301         getFmqUnsyncWrite(setupQueue, userFd, service, fmq);
302         return service;
303     }
304 
requestReadFmqUnsync(size_t dataLen,sp<cppITestAidlMsgQ> service)305     bool requestReadFmqUnsync(size_t dataLen, sp<cppITestAidlMsgQ> service) {
306         bool result = false;
307         auto ret = service->requestReadFmqUnsync(dataLen, &result);
308         return result && ret.isOk();
309     }
requestWriteFmqUnsync(size_t dataLen,sp<cppITestAidlMsgQ> service)310     bool requestWriteFmqUnsync(size_t dataLen, sp<cppITestAidlMsgQ> service) {
311         bool result = false;
312         auto ret = service->requestWriteFmqUnsync(dataLen, &result);
313         return result && ret.isOk();
314     }
newQueue()315     cppAidlMessageQueueUnsync* newQueue() {
316         if (mQueue->isValid())
317             return new (std::nothrow) cppAidlMessageQueueUnsync(mQueue->dupeDesc(), false);
318         else
319             return nullptr;
320     }
321 
322     sp<cppITestAidlMsgQ> mService;
323     cppAidlMessageQueueUnsync* mQueue = nullptr;
324 };
325 
326 // Specialize for HIDL
327 template <>
328 class ClientUnsyncTestBase<MessageQueueUnsync> : public ::testing::Test {
329   protected:
waitGetTestService()330     static sp<ITestMsgQ> waitGetTestService() {
331         if (isHidlSupported()) {
332             android::hardware::details::setTrebleTestingOverride(true);
333             // waitForHwService is required because ITestMsgQ is not in manifest.xml.
334             // "Real" HALs shouldn't be doing this.
335             waitForHwService(ITestMsgQ::descriptor, "default");
336             sp<ITestMsgQ> service = ITestMsgQ::getService();
337             CHECK(nullptr != service);
338             CHECK(service->isRemote() == true);
339             return service;
340         } else {
341             return nullptr;
342         }
343     }
getFmqUnsyncWrite(bool configureFmq,bool userFd,sp<ITestMsgQ> service,MessageQueueUnsync ** queue)344     bool getFmqUnsyncWrite(bool configureFmq, bool userFd, sp<ITestMsgQ> service,
345                            MessageQueueUnsync** queue) {
346         if (!service) {
347             return false;
348         }
349         service->getFmqUnsyncWrite(configureFmq, userFd,
350                                    [queue](bool ret, const MQDescriptorUnsync<int32_t>& in) {
351                                        ASSERT_TRUE(ret);
352                                        *queue = new (std::nothrow) MessageQueueUnsync(in, false);
353                                    });
354         return true;
355     }
356 
getQueue(MessageQueueUnsync ** fmq,bool setupQueue,bool userFd)357     sp<ITestMsgQ> getQueue(MessageQueueUnsync** fmq, bool setupQueue, bool userFd) {
358         sp<ITestMsgQ> service = waitGetTestService();
359         if (service == nullptr) return nullptr;
360         getFmqUnsyncWrite(setupQueue, userFd, service, fmq);
361         return service;
362     }
363 
requestReadFmqUnsync(size_t dataLen,sp<ITestMsgQ> service)364     bool requestReadFmqUnsync(size_t dataLen, sp<ITestMsgQ> service) {
365         auto ret = service->requestReadFmqUnsync(dataLen);
366         return ret && ret.isOk();
367     }
requestWriteFmqUnsync(size_t dataLen,sp<ITestMsgQ> service)368     bool requestWriteFmqUnsync(size_t dataLen, sp<ITestMsgQ> service) {
369         auto ret = service->requestWriteFmqUnsync(dataLen);
370         return ret && ret.isOk();
371     }
372 
newQueue()373     MessageQueueUnsync* newQueue() {
374         return new (std::nothrow) MessageQueueUnsync(*mQueue->getDesc(), false);
375     }
376 
377     sp<ITestMsgQ> mService;
378     MessageQueueUnsync* mQueue = nullptr;
379 };
380 
381 TYPED_TEST_CASE(UnsynchronizedWriteClientMultiProcess, UnsyncTypes);
382 template <typename T>
383 class UnsynchronizedWriteClientMultiProcess : public ClientUnsyncTestBase<typename T::MQType> {};
384 
385 TYPED_TEST_CASE(SynchronizedReadWriteClient, SyncTypes);
386 template <typename T>
387 class SynchronizedReadWriteClient : public ClientSyncTestBase<typename T::MQType> {
388   protected:
TearDown()389     virtual void TearDown() {
390         delete mQueue;
391     }
392 
SetUp()393     virtual void SetUp() {
394         this->mService = this->waitGetTestService();
395         if (this->mService == nullptr) GTEST_SKIP() << "HIDL is not supported";
396         static constexpr size_t kSyncElementSizeBytes = sizeof(int32_t);
397         android::base::unique_fd ringbufferFd;
398         if (T::UserFd) {
399             ringbufferFd.reset(::ashmem_create_region(
400                     "SyncReadWrite", kNumElementsInSyncQueue * kSyncElementSizeBytes));
401         }
402         // create a queue on the client side
403         mQueue = new (std::nothrow) typename T::MQType(
404                 kNumElementsInSyncQueue, true /* configure event flag word */,
405                 std::move(ringbufferFd), kNumElementsInSyncQueue * kSyncElementSizeBytes);
406         ASSERT_NE(nullptr, mQueue);
407         ASSERT_TRUE(mQueue->isValid());
408         ASSERT_EQ(mQueue->getQuantumCount(), kNumElementsInSyncQueue);
409 
410         // tell server to set up the queue on its end
411         ASSERT_TRUE(this->configureFmqSyncReadWrite(mQueue));
412     }
413 
414     typename T::MQType* mQueue = nullptr;
415 };
416 
417 TYPED_TEST_CASE(UnsynchronizedWriteClient, UnsyncTypes);
418 template <typename T>
419 class UnsynchronizedWriteClient : public ClientUnsyncTestBase<typename T::MQType> {
420   protected:
TearDown()421     virtual void TearDown() { delete this->mQueue; }
422 
SetUp()423     virtual void SetUp() {
424         this->mService = this->waitGetTestService();
425         if (this->mService == nullptr) GTEST_SKIP() << "HIDL is not supported";
426         this->getFmqUnsyncWrite(true, false, this->mService, &this->mQueue);
427         ASSERT_NE(nullptr, this->mQueue);
428         ASSERT_TRUE(this->mQueue->isValid());
429         mNumMessagesMax = this->mQueue->getQuantumCount();
430     }
431 
432     size_t mNumMessagesMax = 0;
433 };
434 
435 /*
436  * Utility function to verify data read from the fast message queue.
437  */
verifyData(int32_t * data,size_t count)438 bool verifyData(int32_t* data, size_t count) {
439     for (size_t i = 0; i < count; i++) {
440         if (data[i] != i) return false;
441     }
442     return true;
443 }
444 
445 /*
446  * Utility function to initialize data to be written to the FMQ
447  */
initData(int32_t * data,size_t count)448 inline void initData(int32_t* data, size_t count) {
449     for (size_t i = 0; i < count; i++) {
450         data[i] = i;
451     }
452 }
453 
454 /*
455  * Verify that for an unsynchronized flavor of FMQ, multiple readers
456  * can recover from a write overflow condition.
457  */
TYPED_TEST(UnsynchronizedWriteClientMultiProcess,MultipleReadersAfterOverflow)458 TYPED_TEST(UnsynchronizedWriteClientMultiProcess, MultipleReadersAfterOverflow) {
459     const size_t dataLen = 16;
460 
461     pid_t pid;
462     /* creating first reader process */
463     if ((pid = fork()) == 0) {
464         typename TypeParam::MQType* queue = nullptr;
465         auto service =
466                 this->getQueue(&queue, true /* setupQueue */, TypeParam::UserFd /* userFd */);
467         ASSERT_NE(service, nullptr);
468         ASSERT_NE(queue, nullptr);
469         ASSERT_TRUE(queue->isValid());
470 
471         size_t numMessagesMax = queue->getQuantumCount();
472 
473         // The following two writes will cause a write overflow.
474         auto ret = this->requestWriteFmqUnsync(numMessagesMax, service);
475         ASSERT_TRUE(ret);
476 
477         ret = this->requestWriteFmqUnsync(1, service);
478         ASSERT_TRUE(ret);
479 
480         // The following read should fail due to the overflow.
481         std::vector<int32_t> readData(numMessagesMax);
482         ASSERT_FALSE(queue->read(&readData[0], numMessagesMax));
483 
484         /*
485          * Request another write to verify that the reader can recover from the
486          * overflow condition.
487          */
488         ASSERT_LT(dataLen, numMessagesMax);
489         ret = this->requestWriteFmqUnsync(dataLen, service);
490         ASSERT_TRUE(ret);
491 
492         // Verify that the read is successful.
493         ASSERT_TRUE(queue->read(&readData[0], dataLen));
494 
495         delete queue;
496         exit(0);
497     }
498 
499     ASSERT_GT(pid, 0 /* parent should see PID greater than 0 for a good fork */);
500 
501     int status;
502     // wait for the first reader process to exit.
503     ASSERT_EQ(pid, waitpid(pid, &status, 0 /* options */));
504 
505     // creating second reader process.
506     if ((pid = fork()) == 0) {
507         typename TypeParam::MQType* queue = nullptr;
508         auto service = this->getQueue(&queue, false /* setupQueue */, false /* userFd */);
509         ASSERT_NE(service, nullptr);
510         ASSERT_NE(queue, nullptr);
511         ASSERT_TRUE(queue->isValid());
512 
513         // This read should fail due to the write overflow.
514         std::vector<int32_t> readData(dataLen);
515         ASSERT_FALSE(queue->read(&readData[0], dataLen));
516 
517         /*
518          * Request another write to verify that the process that recover from
519          * the overflow condition.
520          */
521         auto ret = this->requestWriteFmqUnsync(dataLen, service);
522         ASSERT_TRUE(ret);
523 
524         // verify that the read is successful.
525         ASSERT_TRUE(queue->read(&readData[0], dataLen));
526 
527         delete queue;
528         exit(0);
529     }
530 
531     ASSERT_GT(pid, 0 /* parent should see PID greater than 0 for a good fork */);
532     ASSERT_EQ(pid, waitpid(pid, &status, 0 /* options */));
533 }
534 
535 /*
536  * Test that basic blocking works using readBlocking()/writeBlocking() APIs
537  * using the EventFlag object owned by FMQ.
538  */
TYPED_TEST(SynchronizedReadWriteClient,BlockingReadWrite1)539 TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWrite1) {
540     const size_t dataLen = 64;
541     bool ret = false;
542     /*
543      * Request service to perform a blocking read. This call is oneway and will
544      * return immediately.
545      */
546     this->mService->requestBlockingRead(dataLen);
547     {
548         std::array<int32_t, dataLen> data = {0};
549         ret = this->mQueue->writeBlocking(
550                 data.data(), data.size(),
551                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
552                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
553                 5000000000 /* timeOutNanos */);
554         ASSERT_TRUE(ret);
555     }
556     {
557         std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
558         ret = this->mQueue->writeBlocking(
559                 data.data(), data.size(),
560                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
561                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
562                 5000000000 /* timeOutNanos */);
563         ASSERT_TRUE(ret);
564     }
565 }
566 
567 /*
568  * Test that basic blocking works using readBlocking()/writeBlocking() APIs
569  * using the EventFlag object owned by FMQ and using the default EventFlag
570  * notification bit mask.
571  */
TYPED_TEST(SynchronizedReadWriteClient,BlockingReadWrite2)572 TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWrite2) {
573     const size_t dataLen = 64;
574     bool ret = false;
575 
576     /*
577      * Request service to perform a blocking read using default EventFlag
578      * notification bit mask. This call is oneway and will
579      * return immediately.
580      */
581     this->mService->requestBlockingReadDefaultEventFlagBits(dataLen);
582 
583     /* Cause a context switch to allow service to block */
584     sched_yield();
585     {
586         std::array<int32_t, dataLen> data = {0};
587         ret = this->mQueue->writeBlocking(data.data(), data.size());
588         ASSERT_TRUE(ret);
589     }
590 
591     /*
592      * If the blocking read was successful, another write of size
593      * kNumElementsInSyncQueue will succeed.
594      */
595     {
596         std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
597         ret = this->mQueue->writeBlocking(data.data(), data.size(), 5000000000 /* timeOutNanos */);
598         ASSERT_TRUE(ret);
599     }
600 }
601 
602 /*
603  * Test that repeated blocking reads and writes work using readBlocking()/writeBlocking() APIs
604  * using the EventFlag object owned by FMQ.
605  * Each write operation writes the same amount of data as a single read
606  * operation.
607  */
TYPED_TEST(SynchronizedReadWriteClient,BlockingReadWriteRepeat1)608 TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWriteRepeat1) {
609     const size_t dataLen = 64;
610     bool ret = false;
611 
612     /*
613      * Request service to perform a blocking read of 64 elements. This call is
614      * oneway and will return immediately.
615      */
616     const size_t writeCount = kNumElementsInSyncQueue;
617     this->mService->requestBlockingReadRepeat(dataLen, writeCount);
618     /*
619      * Write 64 elements into the queue for the service to consume
620      */
621     {
622         std::array<int32_t, dataLen> data = {0};
623         for (size_t i = 0; i < writeCount; i++) {
624             ret = this->mQueue->writeBlocking(
625                     data.data(), data.size(),
626                     static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
627                     static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
628                     5000000000 /* timeOutNanos */);
629             ASSERT_TRUE(ret);
630         }
631     }
632     /*
633      * The queue should be totally empty now, so filling it up entirely with one
634      * blocking write should be successful.
635      */
636     {
637         std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
638         ret = this->mQueue->writeBlocking(
639                 data.data(), data.size(),
640                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
641                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
642                 5000000000 /* timeOutNanos */);
643 
644         ASSERT_TRUE(ret);
645     }
646 }
647 
648 /*
649  * Test that repeated blocking reads and writes work using readBlocking()/writeBlocking() APIs
650  * using the EventFlag object owned by FMQ. Each read operation reads twice the
651  * amount of data as a single write.
652  *
653  */
TYPED_TEST(SynchronizedReadWriteClient,BlockingReadWriteRepeat2)654 TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWriteRepeat2) {
655     const size_t dataLen = 64;
656     bool ret = false;
657     /*
658      * Request service to perform a repeated blocking read. This call is oneway
659      * and will return immediately. It will read 64 * 2 elements with each
660      * blocking read, for a total of writeCount / 2 calls.
661      */
662     const size_t writeCount = kNumElementsInSyncQueue;
663     this->mService->requestBlockingReadRepeat(dataLen * 2, writeCount / 2);
664     /*
665      * Write 64 elements into the queue writeCount times
666      */
667     {
668         std::array<int32_t, dataLen> data = {0};
669         for (size_t i = 0; i < writeCount; i++) {
670             ret = this->mQueue->writeBlocking(
671                     data.data(), data.size(),
672                     static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
673                     static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
674                     5000000000 /* timeOutNanos */);
675             ASSERT_TRUE(ret);
676         }
677     }
678     /*
679      * The queue should be totally empty now, so filling it up entirely with one
680      * blocking write should be successful.
681      */
682     {
683         std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
684         ret = this->mQueue->writeBlocking(
685                 data.data(), data.size(),
686                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
687                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
688                 5000000000 /* timeOutNanos */);
689         ASSERT_TRUE(ret);
690     }
691 }
692 
693 /*
694  * Test that basic blocking works using readBlocking()/writeBlocking() APIs
695  * using the EventFlag object owned by FMQ. Each write operation writes twice
696  * the amount of data as a single read.
697  */
TYPED_TEST(SynchronizedReadWriteClient,BlockingReadWriteRepeat3)698 TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWriteRepeat3) {
699     const size_t dataLen = 64;
700     bool ret = false;
701 
702     /*
703      * Request service to perform a repeated blocking read. This call is oneway
704      * and will return immediately. It will read 64 / 2 elements with each
705      * blocking read, for a total of writeCount * 2 calls.
706      */
707     size_t writeCount = 1024;
708     this->mService->requestBlockingReadRepeat(dataLen / 2, writeCount * 2);
709     /*
710      * Write 64 elements into the queue writeCount times
711      */
712     {
713         std::array<int32_t, dataLen> data = {0};
714         for (size_t i = 0; i < writeCount; i++) {
715             ret = this->mQueue->writeBlocking(
716                     data.data(), data.size(),
717                     static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
718                     static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
719                     5000000000 /* timeOutNanos */);
720             ASSERT_TRUE(ret);
721         }
722     }
723     /*
724      * The queue should be totally empty now, so filling it up entirely with one
725      * blocking write should be successful.
726      */
727     {
728         std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
729         ret = this->mQueue->writeBlocking(
730                 data.data(), data.size(),
731                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
732                 static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
733                 5000000000 /* timeOutNanos */);
734         ASSERT_TRUE(ret);
735     }
736 }
737 
738 /*
739  * Test that writeBlocking()/readBlocking() APIs do not block on
740  * attempts to write/read 0 messages and return true.
741  */
TYPED_TEST(SynchronizedReadWriteClient,BlockingReadWriteZeroMessages)742 TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWriteZeroMessages) {
743     int32_t data = 0;
744 
745     /*
746      * Trigger a blocking write for zero messages with no timeout.
747      */
748     bool ret = this->mQueue->writeBlocking(
749             &data, 0, static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
750             static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY));
751     ASSERT_TRUE(ret);
752 
753     /*
754      * Trigger a blocking read for zero messages with no timeout.
755      */
756     ret = this->mQueue->readBlocking(
757             &data, 0, static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
758             static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY));
759     ASSERT_TRUE(ret);
760 }
761 
762 /*
763  * Request mService to write a small number of messages
764  * to the FMQ. Read and verify data.
765  */
TYPED_TEST(SynchronizedReadWriteClient,SmallInputReaderTest1)766 TYPED_TEST(SynchronizedReadWriteClient, SmallInputReaderTest1) {
767     const size_t dataLen = 16;
768     ASSERT_LE(dataLen, kNumElementsInSyncQueue);
769     bool ret = this->requestWriteFmqSync(dataLen);
770     ASSERT_TRUE(ret);
771     int32_t readData[dataLen] = {};
772     ASSERT_TRUE(this->mQueue->read(readData, dataLen));
773     ASSERT_TRUE(verifyData(readData, dataLen));
774 }
775 
776 /*
777  * Request mService to write a message to the queue followed by a beginRead().
778  * Get a pointer to the memory region for the that first message. Set the write
779  * counter to the last byte in the ring buffer. Request another write from
780  * mService. The write should fail because the write address is misaligned.
781  */
TYPED_TEST(SynchronizedReadWriteClient,MisalignedWriteCounter)782 TYPED_TEST(SynchronizedReadWriteClient, MisalignedWriteCounter) {
783     if (TypeParam::UserFd) {
784         // When using the second FD for the ring buffer, we can't get to the read/write
785         // counters from a pointer to the ring buffer, so no sense in testing.
786         GTEST_SKIP();
787     }
788     const size_t dataLen = 1;
789     ASSERT_LE(dataLen, kNumElementsInSyncQueue);
790     bool ret = this->requestWriteFmqSync(dataLen);
791     ASSERT_TRUE(ret);
792     // begin read and get a MemTransaction object for the first object in the queue
793     typename TypeParam::MQType::MemTransaction tx;
794     ASSERT_TRUE(this->mQueue->beginRead(dataLen, &tx));
795     // get a pointer to the beginning of the ring buffer
796     const auto& region = tx.getFirstRegion();
797     int32_t* firstStart = region.getAddress();
798 
799     // because this is the first location in the ring buffer, we can get
800     // access to the read and write pointer stored in the fd. 8 bytes back for the
801     // write counter and 16 bytes back for the read counter
802     uint64_t* writeCntr = (uint64_t*)((uint8_t*)firstStart - 8);
803 
804     // set it to point to the very last byte in the ring buffer
805     *(writeCntr) = this->mQueue->getQuantumCount() * this->mQueue->getQuantumSize() - 1;
806     ASSERT_TRUE(*writeCntr % sizeof(int32_t) != 0);
807 
808     // this is not actually necessary, but it's the expected the pattern.
809     this->mQueue->commitRead(dataLen);
810 
811     // This next write will be misaligned and will overlap outside of the ring buffer.
812     // The write should fail.
813     ret = this->requestWriteFmqSync(dataLen);
814     EXPECT_FALSE(ret);
815 }
816 
817 /*
818  * Request mService to write a small number of messages
819  * to the FMQ. Read and verify each message using
820  * beginRead/Commit read APIs.
821  */
TYPED_TEST(SynchronizedReadWriteClient,SmallInputReaderTest2)822 TYPED_TEST(SynchronizedReadWriteClient, SmallInputReaderTest2) {
823     const size_t dataLen = 16;
824     ASSERT_LE(dataLen, kNumElementsInSyncQueue);
825     auto ret = this->requestWriteFmqSync(dataLen);
826     ASSERT_TRUE(ret);
827 
828     typename TypeParam::MQType::MemTransaction tx;
829     ASSERT_TRUE(this->mQueue->beginRead(dataLen, &tx));
830 
831     auto first = tx.getFirstRegion();
832     auto second = tx.getSecondRegion();
833     size_t firstRegionLength = first.getLength();
834 
835     for (size_t i = 0; i < dataLen; i++) {
836         if (i < firstRegionLength) {
837             ASSERT_EQ(i, *(first.getAddress() + i));
838         } else {
839             ASSERT_EQ(i, *(second.getAddress() + i - firstRegionLength));
840         }
841     }
842 
843     ASSERT_TRUE(this->mQueue->commitRead(dataLen));
844 }
845 
846 /*
847  * Write a small number of messages to FMQ. Request
848  * mService to read and verify that the write was successful.
849  */
TYPED_TEST(SynchronizedReadWriteClient,SmallInputWriterTest1)850 TYPED_TEST(SynchronizedReadWriteClient, SmallInputWriterTest1) {
851     const size_t dataLen = 16;
852     ASSERT_LE(dataLen, kNumElementsInSyncQueue);
853     size_t originalCount = this->mQueue->availableToWrite();
854     int32_t data[dataLen];
855     initData(data, dataLen);
856     ASSERT_TRUE(this->mQueue->write(data, dataLen));
857     bool ret = this->requestReadFmqSync(dataLen);
858     ASSERT_TRUE(ret);
859     size_t availableCount = this->mQueue->availableToWrite();
860     ASSERT_EQ(originalCount, availableCount);
861 }
862 
863 /*
864  * Write a message to the queue, get a pointer to the memory region for that
865  * first message. Set the write counter to the last byte in the ring buffer.
866  * Try another write, it should fail because the write address is misaligned.
867  */
TYPED_TEST(SynchronizedReadWriteClient,MisalignedWriteCounterClientSide)868 TYPED_TEST(SynchronizedReadWriteClient, MisalignedWriteCounterClientSide) {
869     if (TypeParam::UserFd) {
870         // When using the second FD for the ring buffer, we can't get to the read/write
871         // counters from a pointer to the ring buffer, so no sense in testing.
872         GTEST_SKIP();
873     }
874 
875     bool errorCallbackTriggered = false;
876     auto errorHandler = [&errorCallbackTriggered](TypeParam::MQType::Error error, std::string&&) {
877         if (error == TypeParam::MQType::Error::POINTER_CORRUPTION) {
878             errorCallbackTriggered = true;
879         }
880     };
881     this->mQueue->setErrorHandler(errorHandler);
882     EXPECT_FALSE(errorCallbackTriggered);
883 
884     const size_t dataLen = 1;
885     ASSERT_LE(dataLen, kNumElementsInSyncQueue);
886     int32_t data[dataLen];
887     initData(data, dataLen);
888     // begin write and get a MemTransaction object for the first object in the queue
889     typename TypeParam::MQType::MemTransaction tx;
890     ASSERT_TRUE(this->mQueue->beginWrite(dataLen, &tx));
891     EXPECT_FALSE(errorCallbackTriggered);
892 
893     // get a pointer to the beginning of the ring buffer
894     const auto& region = tx.getFirstRegion();
895     int32_t* firstStart = region.getAddress();
896 
897     // because this is the first location in the ring buffer, we can get
898     // access to the read and write pointer stored in the fd. 8 bytes back for the
899     // write counter and 16 bytes back for the read counter
900     uint64_t* writeCntr = (uint64_t*)((uint8_t*)firstStart - 8);
901 
902     // set it to point to the very last byte in the ring buffer
903     *(writeCntr) = this->mQueue->getQuantumCount() * this->mQueue->getQuantumSize() - 1;
904     ASSERT_TRUE(*writeCntr % sizeof(int32_t) != 0);
905     EXPECT_FALSE(errorCallbackTriggered);
906 
907     ASSERT_TRUE(this->mQueue->commitWrite(dataLen));
908     EXPECT_FALSE(errorCallbackTriggered);
909 
910     // This next write will be misaligned and will overlap outside of the ring buffer.
911     // The write should fail.
912     EXPECT_FALSE(this->mQueue->write(data, dataLen));
913     EXPECT_TRUE(errorCallbackTriggered);
914 
915     errorCallbackTriggered = false;
916     EXPECT_EQ(0, this->mQueue->availableToWrite());
917     EXPECT_TRUE(errorCallbackTriggered);
918 
919     // Check that it is possible to reset the error handler.
920     errorCallbackTriggered = false;
921     this->mQueue->setErrorHandler(nullptr);
922     EXPECT_EQ(0, this->mQueue->availableToWrite());
923     EXPECT_FALSE(errorCallbackTriggered);
924 }
925 
926 /*
927  * Write a small number of messages to FMQ using the beginWrite()/CommitWrite()
928  * APIs. Request mService to read and verify that the write was successful.
929  */
TYPED_TEST(SynchronizedReadWriteClient,SmallInputWriterTest2)930 TYPED_TEST(SynchronizedReadWriteClient, SmallInputWriterTest2) {
931     const size_t dataLen = 16;
932     ASSERT_LE(dataLen, kNumElementsInSyncQueue);
933     size_t originalCount = this->mQueue->availableToWrite();
934     int32_t data[dataLen];
935     initData(data, dataLen);
936 
937     typename TypeParam::MQType::MemTransaction tx;
938     ASSERT_TRUE(this->mQueue->beginWrite(dataLen, &tx));
939 
940     auto first = tx.getFirstRegion();
941     auto second = tx.getSecondRegion();
942 
943     size_t firstRegionLength = first.getLength();
944     int32_t* firstBaseAddress = first.getAddress();
945     int32_t* secondBaseAddress = second.getAddress();
946 
947     for (size_t i = 0; i < dataLen; i++) {
948         if (i < firstRegionLength) {
949             *(firstBaseAddress + i) = i;
950         } else {
951             *(secondBaseAddress + i - firstRegionLength) = i;
952         }
953     }
954 
955     ASSERT_TRUE(this->mQueue->commitWrite(dataLen));
956 
957     auto ret = this->requestReadFmqSync(dataLen);
958     // ASSERT_TRUE(ret.isOk());
959     ASSERT_TRUE(ret);
960     size_t availableCount = this->mQueue->availableToWrite();
961     ASSERT_EQ(originalCount, availableCount);
962 }
963 
964 /*
965  * Verify that the FMQ is empty and read fails when it is empty.
966  */
TYPED_TEST(SynchronizedReadWriteClient,ReadWhenEmpty)967 TYPED_TEST(SynchronizedReadWriteClient, ReadWhenEmpty) {
968     ASSERT_EQ(0UL, this->mQueue->availableToRead());
969     const size_t numMessages = 2;
970     ASSERT_LE(numMessages, kNumElementsInSyncQueue);
971     int32_t readData[numMessages];
972     ASSERT_FALSE(this->mQueue->read(readData, numMessages));
973 }
974 
975 /*
976  * Verify FMQ is empty.
977  * Write enough messages to fill it.
978  * Verify availableToWrite() method returns is zero.
979  * Try writing another message and verify that
980  * the attempted write was unsuccessful. Request mService
981  * to read and verify the messages in the FMQ.
982  */
TYPED_TEST(SynchronizedReadWriteClient,WriteWhenFull)983 TYPED_TEST(SynchronizedReadWriteClient, WriteWhenFull) {
984     std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
985     initData(data.data(), data.size());
986     ASSERT_TRUE(this->mQueue->write(data.data(), data.size()));
987     ASSERT_EQ(0UL, this->mQueue->availableToWrite());
988     ASSERT_FALSE(this->mQueue->write(&data[0], 1));
989     bool ret = this->requestReadFmqSync(data.size());
990     ASSERT_TRUE(ret);
991 }
992 
993 /*
994  * Verify FMQ is empty.
995  * Request mService to write data equal to queue size.
996  * Read and verify data in mQueue.
997  */
TYPED_TEST(SynchronizedReadWriteClient,LargeInputTest1)998 TYPED_TEST(SynchronizedReadWriteClient, LargeInputTest1) {
999     bool ret = this->requestWriteFmqSync(kNumElementsInSyncQueue);
1000     ASSERT_TRUE(ret);
1001     std::vector<int32_t> readData(kNumElementsInSyncQueue);
1002     ASSERT_TRUE(this->mQueue->read(&readData[0], kNumElementsInSyncQueue));
1003     ASSERT_TRUE(verifyData(&readData[0], kNumElementsInSyncQueue));
1004 }
1005 
1006 /*
1007  * Request mService to write more than maximum number of messages to the FMQ.
1008  * Verify that the write fails. Verify that availableToRead() method
1009  * still returns 0 and verify that attempt to read fails.
1010  */
TYPED_TEST(SynchronizedReadWriteClient,LargeInputTest2)1011 TYPED_TEST(SynchronizedReadWriteClient, LargeInputTest2) {
1012     ASSERT_EQ(0UL, this->mQueue->availableToRead());
1013     const size_t numMessages = 2048;
1014     ASSERT_GT(numMessages, kNumElementsInSyncQueue);
1015     bool ret = this->requestWriteFmqSync(numMessages);
1016     ASSERT_FALSE(ret);
1017     int32_t readData;
1018     ASSERT_EQ(0UL, this->mQueue->availableToRead());
1019     ASSERT_FALSE(this->mQueue->read(&readData, 1));
1020 }
1021 
1022 /*
1023  * Write until FMQ is full.
1024  * Verify that the number of messages available to write
1025  * is equal to mNumMessagesMax.
1026  * Verify that another write attempt fails.
1027  * Request mService to read. Verify read count.
1028  */
1029 
TYPED_TEST(SynchronizedReadWriteClient,LargeInputTest3)1030 TYPED_TEST(SynchronizedReadWriteClient, LargeInputTest3) {
1031     std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
1032     initData(data.data(), data.size());
1033     ASSERT_TRUE(this->mQueue->write(data.data(), data.size()));
1034     ASSERT_EQ(0UL, this->mQueue->availableToWrite());
1035     ASSERT_FALSE(this->mQueue->write(data.data(), 1));
1036 
1037     bool ret = this->requestReadFmqSync(data.size());
1038     ASSERT_TRUE(ret);
1039 }
1040 
1041 /*
1042  * Confirm that the FMQ is empty. Request mService to write to FMQ.
1043  * Do multiple reads to empty FMQ and verify data.
1044  */
TYPED_TEST(SynchronizedReadWriteClient,MultipleRead)1045 TYPED_TEST(SynchronizedReadWriteClient, MultipleRead) {
1046     const size_t chunkSize = 100;
1047     const size_t chunkNum = 5;
1048     const size_t numMessages = chunkSize * chunkNum;
1049     ASSERT_LE(numMessages, kNumElementsInSyncQueue);
1050     size_t availableToRead = this->mQueue->availableToRead();
1051     size_t expectedCount = 0;
1052     ASSERT_EQ(expectedCount, availableToRead);
1053     bool ret = this->requestWriteFmqSync(numMessages);
1054     ASSERT_TRUE(ret);
1055     int32_t readData[numMessages] = {};
1056     for (size_t i = 0; i < chunkNum; i++) {
1057         ASSERT_TRUE(this->mQueue->read(readData + i * chunkSize, chunkSize));
1058     }
1059     ASSERT_TRUE(verifyData(readData, numMessages));
1060 }
1061 
1062 /*
1063  * Write to FMQ in bursts.
1064  * Request mService to read data. Verify the read was successful.
1065  */
TYPED_TEST(SynchronizedReadWriteClient,MultipleWrite)1066 TYPED_TEST(SynchronizedReadWriteClient, MultipleWrite) {
1067     const size_t chunkSize = 100;
1068     const size_t chunkNum = 5;
1069     const size_t numMessages = chunkSize * chunkNum;
1070     ASSERT_LE(numMessages, kNumElementsInSyncQueue);
1071     int32_t data[numMessages];
1072     initData(&data[0], numMessages);
1073 
1074     for (size_t i = 0; i < chunkNum; i++) {
1075         ASSERT_TRUE(this->mQueue->write(data + i * chunkSize, chunkSize));
1076     }
1077     bool ret = this->requestReadFmqSync(numMessages);
1078     ASSERT_TRUE(ret);
1079 }
1080 
1081 /*
1082  * Write enough messages into the FMQ to fill half of it.
1083  * Request mService to read back the same.
1084  * Write mNumMessagesMax messages into the queue. This should cause a
1085  * wrap around. Request mService to read and verify the data.
1086  */
TYPED_TEST(SynchronizedReadWriteClient,ReadWriteWrapAround)1087 TYPED_TEST(SynchronizedReadWriteClient, ReadWriteWrapAround) {
1088     size_t numMessages = kNumElementsInSyncQueue / 2;
1089     std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
1090     initData(data.data(), data.size());
1091     ASSERT_TRUE(this->mQueue->write(&data[0], numMessages));
1092     bool ret = this->requestReadFmqSync(numMessages);
1093     ASSERT_TRUE(ret);
1094     ASSERT_TRUE(this->mQueue->write(data.data(), data.size()));
1095     ret = this->requestReadFmqSync(data.size());
1096     ASSERT_TRUE(ret);
1097 }
1098 
1099 /*
1100  * Use beginWrite/commitWrite/getSlot APIs to test wrap arounds are handled
1101  * correctly.
1102  * Write enough messages into the FMQ to fill half of it
1103  * and read back the same.
1104  * Write mNumMessagesMax messages into the queue. This will cause a
1105  * wrap around. Read and verify the data.
1106  */
TYPED_TEST(SynchronizedReadWriteClient,ReadWriteWrapAround2)1107 TYPED_TEST(SynchronizedReadWriteClient, ReadWriteWrapAround2) {
1108     size_t numMessages = kNumElementsInSyncQueue / 2;
1109     std::vector<int32_t> data(kNumElementsInSyncQueue, 0);
1110     initData(data.data(), data.size());
1111     ASSERT_TRUE(this->mQueue->write(&data[0], numMessages));
1112     auto ret = this->requestReadFmqSync(numMessages);
1113     ASSERT_TRUE(ret);
1114 
1115     /*
1116      * The next write and read will have to deal with with wrap arounds.
1117      */
1118     typename TypeParam::MQType::MemTransaction tx;
1119     ASSERT_TRUE(this->mQueue->beginWrite(data.size(), &tx));
1120 
1121     ASSERT_EQ(tx.getFirstRegion().getLength() + tx.getSecondRegion().getLength(), data.size());
1122 
1123     for (size_t i = 0; i < data.size(); i++) {
1124         int32_t* ptr = tx.getSlot(i);
1125         *ptr = data[i];
1126     }
1127 
1128     ASSERT_TRUE(this->mQueue->commitWrite(data.size()));
1129 
1130     ret = this->requestReadFmqSync(data.size());
1131     ASSERT_TRUE(ret);
1132 }
1133 
1134 /*
1135  * Request this->mService to write a small number of messages
1136  * to the FMQ. Read and verify data.
1137  */
TYPED_TEST(UnsynchronizedWriteClient,SmallInputReaderTest1)1138 TYPED_TEST(UnsynchronizedWriteClient, SmallInputReaderTest1) {
1139     const size_t dataLen = 16;
1140     ASSERT_LE(dataLen, this->mNumMessagesMax);
1141     bool ret = this->requestWriteFmqUnsync(dataLen, this->mService);
1142     ASSERT_TRUE(ret);
1143     int32_t readData[dataLen] = {};
1144     ASSERT_TRUE(this->mQueue->read(readData, dataLen));
1145     ASSERT_TRUE(verifyData(readData, dataLen));
1146 }
1147 
1148 /*
1149  * Write a small number of messages to FMQ. Request
1150  * this->mService to read and verify that the write was successful.
1151  */
TYPED_TEST(UnsynchronizedWriteClient,SmallInputWriterTest1)1152 TYPED_TEST(UnsynchronizedWriteClient, SmallInputWriterTest1) {
1153     const size_t dataLen = 16;
1154     ASSERT_LE(dataLen, this->mNumMessagesMax);
1155     ASSERT_TRUE(this->requestWriteFmqUnsync(dataLen, this->mService));
1156     ASSERT_TRUE(this->requestReadFmqUnsync(dataLen, this->mService));
1157 }
1158 
1159 /*
1160  * Verify that the FMQ is empty and read fails when it is empty.
1161  */
TYPED_TEST(UnsynchronizedWriteClient,ReadWhenEmpty)1162 TYPED_TEST(UnsynchronizedWriteClient, ReadWhenEmpty) {
1163     ASSERT_EQ(0UL, this->mQueue->availableToRead());
1164     const size_t numMessages = 2;
1165     ASSERT_LE(numMessages, this->mNumMessagesMax);
1166     int32_t readData[numMessages];
1167     ASSERT_FALSE(this->mQueue->read(readData, numMessages));
1168 }
1169 
1170 /*
1171  * Verify FMQ is empty.
1172  * Write enough messages to fill it.
1173  * Verify availableToWrite() method returns is zero.
1174  * Try writing another message and verify that
1175  * the attempted write was successful. Request this->mService
1176  * to read the messages in the FMQ and verify that it is unsuccessful.
1177  */
1178 
TYPED_TEST(UnsynchronizedWriteClient,WriteWhenFull)1179 TYPED_TEST(UnsynchronizedWriteClient, WriteWhenFull) {
1180     std::vector<int32_t> data(this->mNumMessagesMax);
1181     initData(&data[0], this->mNumMessagesMax);
1182     ASSERT_TRUE(this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService));
1183     ASSERT_EQ(0UL, this->mQueue->availableToWrite());
1184     ASSERT_TRUE(this->requestWriteFmqUnsync(1, this->mService));
1185     bool ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
1186     ASSERT_FALSE(ret);
1187 }
1188 
1189 /*
1190  * Verify FMQ is empty.
1191  * Request this->mService to write data equal to queue size.
1192  * Read and verify data in this->mQueue.
1193  */
TYPED_TEST(UnsynchronizedWriteClient,LargeInputTest1)1194 TYPED_TEST(UnsynchronizedWriteClient, LargeInputTest1) {
1195     bool ret = this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService);
1196     ASSERT_TRUE(ret);
1197     std::vector<int32_t> data(this->mNumMessagesMax);
1198     ASSERT_TRUE(this->mQueue->read(&data[0], this->mNumMessagesMax));
1199     ASSERT_TRUE(verifyData(&data[0], this->mNumMessagesMax));
1200 }
1201 
1202 /*
1203  * Request this->mService to write more than maximum number of messages to the FMQ.
1204  * Verify that the write fails. Verify that availableToRead() method
1205  * still returns 0 and verify that attempt to read fails.
1206  */
TYPED_TEST(UnsynchronizedWriteClient,LargeInputTest2)1207 TYPED_TEST(UnsynchronizedWriteClient, LargeInputTest2) {
1208     ASSERT_EQ(0UL, this->mQueue->availableToRead());
1209     const size_t numMessages = this->mNumMessagesMax + 1;
1210     bool ret = this->requestWriteFmqUnsync(numMessages, this->mService);
1211     ASSERT_FALSE(ret);
1212     int32_t readData;
1213     ASSERT_EQ(0UL, this->mQueue->availableToRead());
1214     ASSERT_FALSE(this->mQueue->read(&readData, 1));
1215 }
1216 
1217 /*
1218  * Write until FMQ is full.
1219  * Verify that another write attempt is successful.
1220  * Request this->mService to read. Verify that read is unsuccessful
1221  * because of the write overflow.
1222  * Perform another write and verify that the read is successful
1223  * to check if the reader process can recover from the error condition.
1224  */
TYPED_TEST(UnsynchronizedWriteClient,LargeInputTest3)1225 TYPED_TEST(UnsynchronizedWriteClient, LargeInputTest3) {
1226     ASSERT_TRUE(this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService));
1227     ASSERT_EQ(0UL, this->mQueue->availableToWrite());
1228 
1229     int32_t readData;
1230     ASSERT_TRUE(this->requestWriteFmqUnsync(1, this->mService));
1231 
1232     ASSERT_FALSE(this->mQueue->read(&readData, 1));
1233 
1234     // Half of the buffer gets cleared on overflow so single item write will not
1235     // cause another overflow.
1236     ASSERT_TRUE(this->requestWriteFmqUnsync(1, this->mService));
1237 
1238     // Half of the buffer plus a newly written element will be available.
1239     ASSERT_TRUE(this->mQueue->read(&readData, 1));
1240 }
1241 
1242 /*
1243  * Confirm that the FMQ is empty. Request this->mService to write to FMQ.
1244  * Do multiple reads to empty FMQ and verify data.
1245  */
TYPED_TEST(UnsynchronizedWriteClient,MultipleRead)1246 TYPED_TEST(UnsynchronizedWriteClient, MultipleRead) {
1247     const size_t chunkSize = 100;
1248     const size_t chunkNum = 5;
1249     const size_t numMessages = chunkSize * chunkNum;
1250     ASSERT_LE(numMessages, this->mNumMessagesMax);
1251     size_t availableToRead = this->mQueue->availableToRead();
1252     size_t expectedCount = 0;
1253     ASSERT_EQ(expectedCount, availableToRead);
1254     bool ret = this->requestWriteFmqUnsync(numMessages, this->mService);
1255     ASSERT_TRUE(ret);
1256     int32_t readData[numMessages] = {};
1257     for (size_t i = 0; i < chunkNum; i++) {
1258         ASSERT_TRUE(this->mQueue->read(readData + i * chunkSize, chunkSize));
1259     }
1260     ASSERT_TRUE(verifyData(readData, numMessages));
1261 }
1262 
1263 /*
1264  * Write to FMQ in bursts.
1265  * Request this->mService to read data, verify that it was successful.
1266  */
TYPED_TEST(UnsynchronizedWriteClient,MultipleWrite)1267 TYPED_TEST(UnsynchronizedWriteClient, MultipleWrite) {
1268     const size_t chunkSize = 100;
1269     const size_t chunkNum = 5;
1270     const size_t numMessages = chunkSize * chunkNum;
1271     ASSERT_LE(numMessages, this->mNumMessagesMax);
1272     for (size_t i = 0; i < chunkNum; i++) {
1273         ASSERT_TRUE(this->requestWriteFmqUnsync(chunkSize, this->mService));
1274     }
1275     ASSERT_EQ(numMessages, this->mQueue->availableToRead());
1276     int32_t readData[numMessages] = {};
1277     ASSERT_TRUE(this->mQueue->read(readData, numMessages));
1278     // verify that data is filled by the service - the messages will contiain
1279     // 'chunkSize' because that's the value we passed to the service each write.
1280     ASSERT_TRUE(verifyData(readData, chunkSize));
1281 }
1282 
1283 /*
1284  * Write enough messages into the FMQ to fill half of it.
1285  * Request this->mService to read back the same.
1286  * Write this->mNumMessagesMax messages into the queue. This should cause a
1287  * wrap around. Request this->mService to read and verify the data.
1288  */
TYPED_TEST(UnsynchronizedWriteClient,ReadWriteWrapAround)1289 TYPED_TEST(UnsynchronizedWriteClient, ReadWriteWrapAround) {
1290     size_t numMessages = this->mNumMessagesMax / 2;
1291     ASSERT_TRUE(this->requestWriteFmqUnsync(numMessages, this->mService));
1292     ASSERT_TRUE(this->requestReadFmqUnsync(numMessages, this->mService));
1293     ASSERT_TRUE(this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService));
1294     ASSERT_TRUE(this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService));
1295 }
1296 
1297 /*
1298  * Request this->mService to write a small number of messages
1299  * to the FMQ. Read and verify data from two threads configured
1300  * as readers to the FMQ.
1301  */
TYPED_TEST(UnsynchronizedWriteClient,SmallInputMultipleReaderTest)1302 TYPED_TEST(UnsynchronizedWriteClient, SmallInputMultipleReaderTest) {
1303     typename TypeParam::MQType* mQueue2 = this->newQueue();
1304 
1305     ASSERT_NE(nullptr, mQueue2);
1306 
1307     const size_t dataLen = 16;
1308     ASSERT_LE(dataLen, this->mNumMessagesMax);
1309 
1310     bool ret = this->requestWriteFmqUnsync(dataLen, this->mService);
1311     ASSERT_TRUE(ret);
1312 
1313     pid_t pid;
1314     if ((pid = fork()) == 0) {
1315         /* child process */
1316         int32_t readData[dataLen] = {};
1317         ASSERT_TRUE(mQueue2->read(readData, dataLen));
1318         ASSERT_TRUE(verifyData(readData, dataLen));
1319         exit(0);
1320     } else {
1321         ASSERT_GT(pid,
1322                   0 /* parent should see PID greater than 0 for a good fork */);
1323         int32_t readData[dataLen] = {};
1324         ASSERT_TRUE(this->mQueue->read(readData, dataLen));
1325         ASSERT_TRUE(verifyData(readData, dataLen));
1326     }
1327 }
1328 
1329 /*
1330  * Request this->mService to write into the FMQ until it is full.
1331  * Request this->mService to do another write and verify it is successful.
1332  * Use two reader processes to read and verify that both fail.
1333  */
TYPED_TEST(UnsynchronizedWriteClient,OverflowNotificationTest)1334 TYPED_TEST(UnsynchronizedWriteClient, OverflowNotificationTest) {
1335     typename TypeParam::MQType* mQueue2 = this->newQueue();
1336     ASSERT_NE(nullptr, mQueue2);
1337 
1338     bool ret = this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService);
1339     ASSERT_TRUE(ret);
1340     ret = this->requestWriteFmqUnsync(1, this->mService);
1341     ASSERT_TRUE(ret);
1342 
1343     pid_t pid;
1344     if ((pid = fork()) == 0) {
1345         /* child process */
1346         std::vector<int32_t> readData(this->mNumMessagesMax);
1347         ASSERT_FALSE(mQueue2->read(&readData[0], this->mNumMessagesMax));
1348         exit(0);
1349     } else {
1350         ASSERT_GT(pid, 0/* parent should see PID greater than 0 for a good fork */);
1351         std::vector<int32_t> readData(this->mNumMessagesMax);
1352         ASSERT_FALSE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
1353     }
1354 }
1355 
1356 /*
1357  * Make sure a valid queue can be created with different supported types.
1358  * All fundamental or native types should work. An AIDL parcelable that is
1359  * annotated with @FixedSize is supported. A parcelable without it, will cause
1360  * a compilation error.
1361  */
1362 typedef ::testing::Types<FixedParcelable, FixedUnion, EventFlagBits, bool, int8_t, char, char16_t,
1363                          int32_t, int64_t, float, double>
1364         AidlTypeCheckTypes;
1365 
1366 template <typename T>
1367 class AidlTypeChecks : public ::testing::Test {};
1368 
1369 TYPED_TEST_CASE(AidlTypeChecks, AidlTypeCheckTypes);
1370 
TYPED_TEST(AidlTypeChecks,FixedSizeParcelableTest)1371 TYPED_TEST(AidlTypeChecks, FixedSizeParcelableTest) {
1372     android::AidlMessageQueue<TypeParam, UnsynchronizedWrite> queue =
1373             android::AidlMessageQueue<TypeParam, UnsynchronizedWrite>(64);
1374     ASSERT_TRUE(queue.isValid());
1375     // Make sure we can do a simple write/read of any value.
1376     TypeParam writeData[1];
1377     TypeParam readData[1];
1378     EXPECT_TRUE(queue.write(writeData, 1));
1379     EXPECT_TRUE(queue.read(readData, 1));
1380 }
1381