blob: 471ec7bf20bbdde78d6dfb377c12416671b5e43f [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <gtest/gtest.h>
Corey Tabaka52ea25c2017-09-13 18:02:48 -07002#include <poll.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08003#include <private/dvr/buffer_hub_client.h>
Corey Tabaka52ea25c2017-09-13 18:02:48 -07004#include <private/dvr/bufferhub_rpc.h>
5#include <sys/epoll.h>
6#include <sys/eventfd.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08007
8#include <mutex>
9#include <thread>
10
Alex Vakulenko4fe60582017-02-02 11:35:59 -080011#define RETRY_EINTR(fnc_call) \
12 ([&]() -> decltype(fnc_call) { \
13 decltype(fnc_call) result; \
14 do { \
15 result = (fnc_call); \
16 } while (result == -1 && errno == EINTR); \
17 return result; \
18 })()
19
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080020using android::dvr::BufferConsumer;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070021using android::dvr::BufferHubDefs::kConsumerStateMask;
22using android::dvr::BufferHubDefs::kProducerStateBit;
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -070023using android::dvr::BufferHubDefs::IsBufferGained;
24using android::dvr::BufferHubDefs::IsBufferPosted;
25using android::dvr::BufferHubDefs::IsBufferAcquired;
26using android::dvr::BufferHubDefs::IsBufferReleased;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070027using android::dvr::BufferProducer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080028using android::pdx::LocalHandle;
29
30const int kWidth = 640;
31const int kHeight = 480;
32const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
33const int kUsage = 0;
34const uint64_t kContext = 42;
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -070035const size_t kMaxConsumerCount = 63;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080036const int kPollTimeoutMs = 100;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080037
38using LibBufferHubTest = ::testing::Test;
39
40TEST_F(LibBufferHubTest, TestBasicUsage) {
41 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
42 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
43 ASSERT_TRUE(p.get() != nullptr);
44 std::unique_ptr<BufferConsumer> c =
45 BufferConsumer::Import(p->CreateConsumer());
46 ASSERT_TRUE(c.get() != nullptr);
47 // Check that consumers can spawn other consumers.
48 std::unique_ptr<BufferConsumer> c2 =
49 BufferConsumer::Import(c->CreateConsumer());
50 ASSERT_TRUE(c2.get() != nullptr);
51
Corey Tabaka52ea25c2017-09-13 18:02:48 -070052 // Producer state mask is unique, i.e. 1.
53 EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
54 // Consumer state mask cannot have producer bit on.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080055 EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070056 // Consumer state mask must be a single, i.e. power of 2.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080057 EXPECT_NE(c->buffer_state_bit(), 0U);
58 EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070059 // Consumer state mask cannot have producer bit on.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080060 EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070061 // Consumer state mask must be a single, i.e. power of 2.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080062 EXPECT_NE(c2->buffer_state_bit(), 0U);
63 EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070064 // Each consumer should have unique bit.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080065 EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070066
67 // Initial state: producer not available, consumers not available.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080068 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
69 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
70 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070071
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080072 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070073
74 // New state: producer not available, consumers available.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080075 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
76 EXPECT_EQ(1, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
77 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080078
79 uint64_t context;
80 LocalHandle fence;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070081 EXPECT_EQ(0, c->Acquire(&fence, &context));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080082 EXPECT_EQ(kContext, context);
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080083 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
84 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080085
Corey Tabaka52ea25c2017-09-13 18:02:48 -070086 EXPECT_EQ(0, c2->Acquire(&fence, &context));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080087 EXPECT_EQ(kContext, context);
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080088 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
89 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080090
91 EXPECT_EQ(0, c->Release(LocalHandle()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080092 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080093 EXPECT_EQ(0, c2->Discard());
94
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080095 EXPECT_EQ(1, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080096 EXPECT_EQ(0, p->Gain(&fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080097 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
98 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
99 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700100}
101
102TEST_F(LibBufferHubTest, TestEpoll) {
103 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
104 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
105 ASSERT_TRUE(p.get() != nullptr);
106 std::unique_ptr<BufferConsumer> c =
107 BufferConsumer::Import(p->CreateConsumer());
108 ASSERT_TRUE(c.get() != nullptr);
109
110 LocalHandle epoll_fd{epoll_create1(EPOLL_CLOEXEC)};
111 ASSERT_TRUE(epoll_fd.IsValid());
112
113 epoll_event event;
114 std::array<epoll_event, 64> events;
115
116 auto event_sources = p->GetEventSources();
117 ASSERT_LT(event_sources.size(), events.size());
118
119 for (const auto& event_source : event_sources) {
120 event = {.events = event_source.event_mask | EPOLLET,
121 .data = {.fd = p->event_fd()}};
122 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
123 &event));
124 }
125
126 event_sources = c->GetEventSources();
127 ASSERT_LT(event_sources.size(), events.size());
128
129 for (const auto& event_source : event_sources) {
130 event = {.events = event_source.event_mask | EPOLLET,
131 .data = {.fd = c->event_fd()}};
132 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
133 &event));
134 }
135
136 // No events should be signaled initially.
137 ASSERT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 0));
138
139 // Post the producer and check for consumer signal.
140 EXPECT_EQ(0, p->Post({}, kContext));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800141 ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
142 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700143 ASSERT_TRUE(events[0].events & EPOLLIN);
144 ASSERT_EQ(c->event_fd(), events[0].data.fd);
145
146 // Save the event bits to translate later.
147 event = events[0];
148
149 // Check for events again. Edge-triggered mode should prevent any.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800150 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
151 kPollTimeoutMs));
152 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
153 kPollTimeoutMs));
154 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
155 kPollTimeoutMs));
156 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
157 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700158
159 // Translate the events.
160 auto event_status = c->GetEventMask(event.events);
161 ASSERT_TRUE(event_status);
162 ASSERT_TRUE(event_status.get() & EPOLLIN);
163
164 // Check for events again. Edge-triggered mode should prevent any.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800165 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
166 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700167}
168
169TEST_F(LibBufferHubTest, TestStateMask) {
170 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
171 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
172 ASSERT_TRUE(p.get() != nullptr);
173
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700174 // It's ok to create up to kMaxConsumerCount consumer buffers.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700175 uint64_t buffer_state_bits = p->buffer_state_bit();
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700176 std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
177 for (size_t i = 0; i < kMaxConsumerCount; i++) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700178 cs[i] = BufferConsumer::Import(p->CreateConsumer());
179 ASSERT_TRUE(cs[i].get() != nullptr);
180 // Expect all buffers have unique state mask.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800181 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700182 buffer_state_bits |= cs[i]->buffer_state_bit();
183 }
184 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
185
186 // The 64th creation will fail with out-of-memory error.
187 auto state = p->CreateConsumer();
188 EXPECT_EQ(state.error(), E2BIG);
189
190 // Release any consumer should allow us to re-create.
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700191 for (size_t i = 0; i < kMaxConsumerCount; i++) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700192 buffer_state_bits &= ~cs[i]->buffer_state_bit();
193 cs[i] = nullptr;
194 cs[i] = BufferConsumer::Import(p->CreateConsumer());
195 ASSERT_TRUE(cs[i].get() != nullptr);
196 // The released state mask will be reused.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800197 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700198 buffer_state_bits |= cs[i]->buffer_state_bit();
199 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
200 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800201}
202
Corey Tabakad53870c2017-07-06 18:04:27 -0700203TEST_F(LibBufferHubTest, TestStateTransitions) {
204 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
205 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
206 ASSERT_TRUE(p.get() != nullptr);
207 std::unique_ptr<BufferConsumer> c =
208 BufferConsumer::Import(p->CreateConsumer());
209 ASSERT_TRUE(c.get() != nullptr);
210
211 uint64_t context;
212 LocalHandle fence;
213
214 // The producer buffer starts in gained state.
215
216 // Acquire, release, and gain in gained state should fail.
217 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
218 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
219 EXPECT_EQ(-EALREADY, p->Gain(&fence));
220
221 // Post in gained state should succeed.
222 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
223
224 // Post, release, and gain in posted state should fail.
225 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
226 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
227 EXPECT_EQ(-EBUSY, p->Gain(&fence));
228
229 // Acquire in posted state should succeed.
230 EXPECT_LE(0, c->Acquire(&fence, &context));
231
232 // Acquire, post, and gain in acquired state should fail.
233 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
234 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
235 EXPECT_EQ(-EBUSY, p->Gain(&fence));
236
237 // Release in acquired state should succeed.
238 EXPECT_EQ(0, c->Release(LocalHandle()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800239 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabakad53870c2017-07-06 18:04:27 -0700240
241 // Release, acquire, and post in released state should fail.
242 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
243 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
244 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
245
246 // Gain in released state should succeed.
247 EXPECT_EQ(0, p->Gain(&fence));
248
249 // Acquire, release, and gain in gained state should fail.
250 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
251 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
252 EXPECT_EQ(-EALREADY, p->Gain(&fence));
253}
254
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700255TEST_F(LibBufferHubTest, TestAsyncStateTransitions) {
256 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
257 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
258 ASSERT_TRUE(p.get() != nullptr);
259 std::unique_ptr<BufferConsumer> c =
260 BufferConsumer::Import(p->CreateConsumer());
261 ASSERT_TRUE(c.get() != nullptr);
262
263 DvrNativeBufferMetadata metadata;
264 LocalHandle invalid_fence;
265
266 // The producer buffer starts in gained state.
267
268 // Acquire, release, and gain in gained state should fail.
269 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
270 EXPECT_FALSE(invalid_fence.IsValid());
271 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
272 EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
273 EXPECT_FALSE(invalid_fence.IsValid());
274
275 // Post in gained state should succeed.
276 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
277 EXPECT_EQ(p->buffer_state(), c->buffer_state());
278 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
279
280 // Post, release, and gain in posted state should fail.
281 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
282 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
283 EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
284 EXPECT_FALSE(invalid_fence.IsValid());
285
286 // Acquire in posted state should succeed.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800287 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700288 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
289 EXPECT_FALSE(invalid_fence.IsValid());
290 EXPECT_EQ(p->buffer_state(), c->buffer_state());
291 EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
292
293 // Acquire, post, and gain in acquired state should fail.
294 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
295 EXPECT_FALSE(invalid_fence.IsValid());
296 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
297 EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
298 EXPECT_FALSE(invalid_fence.IsValid());
299
300 // Release in acquired state should succeed.
301 EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800302 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700303 EXPECT_EQ(p->buffer_state(), c->buffer_state());
304 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
305
306 // Release, acquire, and post in released state should fail.
307 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
308 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
309 EXPECT_FALSE(invalid_fence.IsValid());
310 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
311
312 // Gain in released state should succeed.
313 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
314 EXPECT_FALSE(invalid_fence.IsValid());
315 EXPECT_EQ(p->buffer_state(), c->buffer_state());
316 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
317
318 // Acquire, release, and gain in gained state should fail.
319 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
320 EXPECT_FALSE(invalid_fence.IsValid());
321 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
322 EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
323 EXPECT_FALSE(invalid_fence.IsValid());
324}
325
326TEST_F(LibBufferHubTest, TestZeroConsumer) {
327 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
328 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
329 ASSERT_TRUE(p.get() != nullptr);
330
331 DvrNativeBufferMetadata metadata;
332 LocalHandle invalid_fence;
333
334 // Newly created.
335 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
336 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
337 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
338
339 // The buffer should stay in posted stay until a consumer picks it up.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800340 EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700341
342 // A new consumer should still be able to acquire the buffer immediately.
343 std::unique_ptr<BufferConsumer> c =
344 BufferConsumer::Import(p->CreateConsumer());
345 ASSERT_TRUE(c.get() != nullptr);
346 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
347 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
348}
349
350TEST_F(LibBufferHubTest, TestMaxConsumers) {
351 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
352 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
353 ASSERT_TRUE(p.get() != nullptr);
354
355 std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
356 for (size_t i = 0; i < kMaxConsumerCount; i++) {
357 cs[i] = BufferConsumer::Import(p->CreateConsumer());
358 ASSERT_TRUE(cs[i].get() != nullptr);
359 EXPECT_TRUE(IsBufferGained(cs[i]->buffer_state()));
360 }
361
362 DvrNativeBufferMetadata metadata;
363 LocalHandle invalid_fence;
364
365 // Post the producer should trigger all consumers to be available.
366 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
367 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
368 for (size_t i = 0; i < kMaxConsumerCount; i++) {
369 EXPECT_TRUE(IsBufferPosted(cs[i]->buffer_state(),
370 cs[i]->buffer_state_bit()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800371 EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700372 EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
373 EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
374 }
375
376 // All consumers have to release before the buffer is considered to be
377 // released.
378 for (size_t i = 0; i < kMaxConsumerCount; i++) {
379 EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
380 EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence));
381 }
382
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800383 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700384 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
385
386 // Buffer state cross all clients must be consistent.
387 for (size_t i = 0; i < kMaxConsumerCount; i++) {
388 EXPECT_EQ(p->buffer_state(), cs[i]->buffer_state());
389 }
390}
391
392TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) {
393 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
394 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
395 ASSERT_TRUE(p.get() != nullptr);
396 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
397
398 std::unique_ptr<BufferConsumer> c =
399 BufferConsumer::Import(p->CreateConsumer());
400 ASSERT_TRUE(c.get() != nullptr);
401 EXPECT_TRUE(IsBufferGained(c->buffer_state()));
402
403 DvrNativeBufferMetadata metadata;
404 LocalHandle invalid_fence;
405
406 // Post the gained buffer should signal already created consumer.
407 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
408 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800409 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700410 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
411 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
412}
413
414TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferPosted) {
415 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
416 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
417 ASSERT_TRUE(p.get() != nullptr);
418 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
419
420 DvrNativeBufferMetadata metadata;
421 LocalHandle invalid_fence;
422
423 // Post the gained buffer before any consumer gets created.
424 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
425 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
426
427 // Newly created consumer should be automatically sigalled.
428 std::unique_ptr<BufferConsumer> c =
429 BufferConsumer::Import(p->CreateConsumer());
430 ASSERT_TRUE(c.get() != nullptr);
431 EXPECT_TRUE(IsBufferPosted(c->buffer_state()));
432 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
433 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
434}
435
436TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
437 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
438 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
439 ASSERT_TRUE(p.get() != nullptr);
440
441 std::unique_ptr<BufferConsumer> c1 =
442 BufferConsumer::Import(p->CreateConsumer());
443 ASSERT_TRUE(c1.get() != nullptr);
444
445 DvrNativeBufferMetadata metadata;
446 LocalHandle invalid_fence;
447
448 // Post, acquire, and release the buffer..
449 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800450 EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700451 EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence));
452 EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence));
453
Jiwen 'Steve' Cai2d89e6b2017-12-06 16:32:22 -0800454 // Note that the next PDX call is on the producer channel, which may be
455 // executed before Release impulse gets executed by bufferhubd. Thus, here we
456 // need to wait until the releasd is confirmed before creating another
457 // consumer.
458 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
459 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
460
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700461 // Create another consumer immediately after the release, should not make the
Jiwen 'Steve' Cai2d89e6b2017-12-06 16:32:22 -0800462 // buffer un-released.
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700463 std::unique_ptr<BufferConsumer> c2 =
464 BufferConsumer::Import(p->CreateConsumer());
465 ASSERT_TRUE(c2.get() != nullptr);
466
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700467 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
468 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
469 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
470}
471
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800472TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
473 struct Metadata {
474 int64_t field1;
475 int64_t field2;
476 };
477 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
478 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
479 ASSERT_TRUE(p.get() != nullptr);
480 std::unique_ptr<BufferConsumer> c =
481 BufferConsumer::Import(p->CreateConsumer());
482 ASSERT_TRUE(c.get() != nullptr);
483
484 Metadata m = {1, 3};
485 EXPECT_EQ(0, p->Post(LocalHandle(), m));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800486 EXPECT_LE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800487
488 LocalHandle fence;
489 Metadata m2 = {};
490 EXPECT_EQ(0, c->Acquire(&fence, &m2));
491 EXPECT_EQ(m.field1, m2.field1);
492 EXPECT_EQ(m.field2, m2.field2);
493
494 EXPECT_EQ(0, c->Release(LocalHandle()));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800495 EXPECT_LT(0, RETRY_EINTR(p->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800496}
497
498TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
499 struct Metadata {
500 int64_t field1;
501 int64_t field2;
502 };
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700503 struct OverSizedMetadata {
504 int64_t field1;
505 int64_t field2;
506 int64_t field3;
507 };
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800508 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
509 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
510 ASSERT_TRUE(p.get() != nullptr);
511 std::unique_ptr<BufferConsumer> c =
512 BufferConsumer::Import(p->CreateConsumer());
513 ASSERT_TRUE(c.get() != nullptr);
514
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700515 // It is illegal to post metadata larger than originally requested during
516 // buffer allocation.
517 OverSizedMetadata evil_meta = {};
518 EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800519 EXPECT_GE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700520
521 // It is ok to post metadata smaller than originally requested during
522 // buffer allocation.
523 int64_t sequence = 42;
524 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800525}
526
527TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
528 struct Metadata {
529 int64_t field1;
530 int64_t field2;
531 };
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700532 struct OverSizedMetadata {
533 int64_t field1;
534 int64_t field2;
535 int64_t field3;
536 };
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800537 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
538 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
539 ASSERT_TRUE(p.get() != nullptr);
540 std::unique_ptr<BufferConsumer> c =
541 BufferConsumer::Import(p->CreateConsumer());
542 ASSERT_TRUE(c.get() != nullptr);
543
544 Metadata m = {1, 3};
545 EXPECT_EQ(0, p->Post(LocalHandle(), m));
546
547 LocalHandle fence;
548 int64_t sequence;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700549 OverSizedMetadata e;
550
551 // It is illegal to acquire metadata larger than originally requested during
552 // buffer allocation.
553 EXPECT_NE(0, c->Acquire(&fence, &e));
554
555 // It is ok to acquire metadata smaller than originally requested during
556 // buffer allocation.
557 EXPECT_EQ(0, c->Acquire(&fence, &sequence));
558 EXPECT_EQ(m.field1, sequence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800559}
560
561TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
562 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
563 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
564 ASSERT_TRUE(p.get() != nullptr);
565 std::unique_ptr<BufferConsumer> c =
566 BufferConsumer::Import(p->CreateConsumer());
567 ASSERT_TRUE(c.get() != nullptr);
568
569 int64_t sequence = 3;
570 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
571
572 LocalHandle fence;
573 EXPECT_EQ(0, c->Acquire(&fence));
574}
575
576TEST_F(LibBufferHubTest, TestWithNoMeta) {
577 std::unique_ptr<BufferProducer> p =
578 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
579 ASSERT_TRUE(p.get() != nullptr);
580 std::unique_ptr<BufferConsumer> c =
581 BufferConsumer::Import(p->CreateConsumer());
582 ASSERT_TRUE(c.get() != nullptr);
583
584 LocalHandle fence;
585
586 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
587 EXPECT_EQ(0, c->Acquire(&fence));
588}
589
590TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) {
591 std::unique_ptr<BufferProducer> p =
592 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
593 ASSERT_TRUE(p.get() != nullptr);
594 std::unique_ptr<BufferConsumer> c =
595 BufferConsumer::Import(p->CreateConsumer());
596 ASSERT_TRUE(c.get() != nullptr);
597
598 int64_t sequence = 3;
599 EXPECT_NE(0, p->Post(LocalHandle(), sequence));
600}
601
602TEST_F(LibBufferHubTest, TestPersistentBufferPersistence) {
603 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
604 kHeight, kFormat, kUsage);
605 ASSERT_NE(nullptr, p);
606
607 // Record the original buffer id for later comparison.
608 const int buffer_id = p->id();
609
610 auto c = BufferConsumer::Import(p->CreateConsumer());
611 ASSERT_NE(nullptr, c);
612
613 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
614
615 // Close the connection to the producer. This should not affect the consumer.
616 p = nullptr;
617
618 LocalHandle fence;
619 EXPECT_EQ(0, c->Acquire(&fence));
620 EXPECT_EQ(0, c->Release(LocalHandle()));
621
622 // Attempt to reconnect to the persistent buffer.
623 p = BufferProducer::Create("TestPersistentBuffer");
624 ASSERT_NE(nullptr, p);
625 EXPECT_EQ(buffer_id, p->id());
626 EXPECT_EQ(0, p->Gain(&fence));
627}
628
629TEST_F(LibBufferHubTest, TestPersistentBufferMismatchParams) {
630 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
631 kHeight, kFormat, kUsage);
632 ASSERT_NE(nullptr, p);
633
634 // Close the connection to the producer.
635 p = nullptr;
636
637 // Mismatch the params.
638 p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth * 2,
639 kHeight, kFormat, kUsage);
640 ASSERT_EQ(nullptr, p);
641}
642
643TEST_F(LibBufferHubTest, TestRemovePersistentBuffer) {
644 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
645 kHeight, kFormat, kUsage);
646 ASSERT_NE(nullptr, p);
647
648 LocalHandle fence;
649 auto c = BufferConsumer::Import(p->CreateConsumer());
650 ASSERT_NE(nullptr, c);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700651 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
652 EXPECT_EQ(0, c->Acquire(&fence));
653 EXPECT_EQ(0, c->Release(LocalHandle()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800654 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800655
656 // Test that removing persistence and closing the producer orphans the
657 // consumer.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700658 EXPECT_EQ(0, p->Gain(&fence));
659 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800660 EXPECT_EQ(0, p->RemovePersistence());
661 p = nullptr;
662
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700663 // Orphaned consumer can acquire the posted buffer one more time in
664 // asynchronous manner. But synchronous call will fail.
665 DvrNativeBufferMetadata meta;
666 EXPECT_EQ(0, c->AcquireAsync(&meta, &fence));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800667 EXPECT_EQ(-EPIPE, c->Release(LocalHandle()));
668}
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700669
670namespace {
671
672int PollFd(int fd, int timeout_ms) {
673 pollfd p = {fd, POLLIN, 0};
674 return poll(&p, 1, timeout_ms);
675}
676
677} // namespace
678
679TEST_F(LibBufferHubTest, TestAcquireFence) {
680 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
681 kWidth, kHeight, kFormat, kUsage, /*metadata_size=*/0);
682 ASSERT_TRUE(p.get() != nullptr);
683 std::unique_ptr<BufferConsumer> c =
684 BufferConsumer::Import(p->CreateConsumer());
685 ASSERT_TRUE(c.get() != nullptr);
686
687 DvrNativeBufferMetadata meta;
688 LocalHandle f1(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
689
690 // Post with unsignaled fence.
691 EXPECT_EQ(0, p->PostAsync(&meta, f1));
692
693 // Should acquire a valid fence.
694 LocalHandle f2;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800695 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700696 EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
697 EXPECT_TRUE(f2.IsValid());
698 // The original fence and acquired fence should have different fd number.
699 EXPECT_NE(f1.Get(), f2.Get());
700 EXPECT_GE(0, PollFd(f2.Get(), 0));
701
702 // Signal the original fence will trigger the new fence.
703 eventfd_write(f1.Get(), 1);
704 // Now the original FD has been signaled.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800705 EXPECT_LT(0, PollFd(f2.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700706
707 // Release the consumer with an invalid fence.
708 EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
709
710 // Should gain an invalid fence.
711 LocalHandle f3;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800712 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700713 EXPECT_EQ(0, p->GainAsync(&meta, &f3));
714 EXPECT_FALSE(f3.IsValid());
715
716 // Post with a signaled fence.
717 EXPECT_EQ(0, p->PostAsync(&meta, f1));
718
719 // Should acquire a valid fence and it's already signalled.
720 LocalHandle f4;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800721 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700722 EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
723 EXPECT_TRUE(f4.IsValid());
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800724 EXPECT_LT(0, PollFd(f4.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700725
726 // Release with an unsignalled fence and signal it immediately after release
727 // without producer gainning.
728 LocalHandle f5(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
729 EXPECT_EQ(0, c->ReleaseAsync(&meta, f5));
730 eventfd_write(f5.Get(), 1);
731
732 // Should gain a valid fence, which is already signaled.
733 LocalHandle f6;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800734 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700735 EXPECT_EQ(0, p->GainAsync(&meta, &f6));
736 EXPECT_TRUE(f6.IsValid());
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800737 EXPECT_LT(0, PollFd(f6.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700738}
739
740TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
741 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
742 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
743 ASSERT_TRUE(p.get() != nullptr);
744 std::unique_ptr<BufferConsumer> c1 =
745 BufferConsumer::Import(p->CreateConsumer());
746 ASSERT_TRUE(c1.get() != nullptr);
747 const uint64_t consumer_state_bit1 = c1->buffer_state_bit();
748
749 DvrNativeBufferMetadata meta;
750 EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
751
752 LocalHandle fence;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800753 EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700754 EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
755 // Destroy the consumer now will make it orphaned and the buffer is still
756 // acquired.
757 c1 = nullptr;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800758 EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700759
760 std::unique_ptr<BufferConsumer> c2 =
761 BufferConsumer::Import(p->CreateConsumer());
762 ASSERT_TRUE(c2.get() != nullptr);
763 const uint64_t consumer_state_bit2 = c2->buffer_state_bit();
764 EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
765
766 // The new consumer is available for acquire.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800767 EXPECT_LT(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700768 EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
769 // Releasing the consumer makes the buffer gainable.
770 EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
771
772 // The buffer is now available for the producer to gain.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800773 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700774
775 // But if another consumer is created in released state.
776 std::unique_ptr<BufferConsumer> c3 =
777 BufferConsumer::Import(p->CreateConsumer());
778 ASSERT_TRUE(c3.get() != nullptr);
779 const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
780 EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
781 // The consumer buffer is not acquirable.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800782 EXPECT_GE(0, RETRY_EINTR(c3->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700783 EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
784
785 // Producer should be able to gain no matter what.
786 EXPECT_EQ(0, p->GainAsync(&meta, &fence));
787}