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