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