blob: 660a2003eaf5b158ec36705137510d803a8c780b [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;
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -070028using android::pdx::LocalChannelHandle;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080029using android::pdx::LocalHandle;
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -070030using android::pdx::Status;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080031
32const int kWidth = 640;
33const int kHeight = 480;
34const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
35const int kUsage = 0;
36const uint64_t kContext = 42;
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -070037const size_t kMaxConsumerCount = 63;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080038const int kPollTimeoutMs = 100;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080039
40using LibBufferHubTest = ::testing::Test;
41
42TEST_F(LibBufferHubTest, TestBasicUsage) {
43 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
44 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
45 ASSERT_TRUE(p.get() != nullptr);
46 std::unique_ptr<BufferConsumer> c =
47 BufferConsumer::Import(p->CreateConsumer());
48 ASSERT_TRUE(c.get() != nullptr);
49 // Check that consumers can spawn other consumers.
50 std::unique_ptr<BufferConsumer> c2 =
51 BufferConsumer::Import(c->CreateConsumer());
52 ASSERT_TRUE(c2.get() != nullptr);
53
Corey Tabaka52ea25c2017-09-13 18:02:48 -070054 // Producer state mask is unique, i.e. 1.
55 EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
56 // Consumer state mask cannot have producer bit on.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080057 EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070058 // Consumer state mask must be a single, i.e. power of 2.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080059 EXPECT_NE(c->buffer_state_bit(), 0U);
60 EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070061 // Consumer state mask cannot have producer bit on.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080062 EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070063 // Consumer state mask must be a single, i.e. power of 2.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080064 EXPECT_NE(c2->buffer_state_bit(), 0U);
65 EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070066 // Each consumer should have unique bit.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080067 EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070068
69 // Initial state: producer not available, consumers not available.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080070 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
71 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
72 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070073
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080074 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070075
76 // New state: producer not available, consumers available.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080077 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
78 EXPECT_EQ(1, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
79 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080080
81 uint64_t context;
82 LocalHandle fence;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070083 EXPECT_EQ(0, c->Acquire(&fence, &context));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080084 EXPECT_EQ(kContext, context);
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080085 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
86 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080087
Corey Tabaka52ea25c2017-09-13 18:02:48 -070088 EXPECT_EQ(0, c2->Acquire(&fence, &context));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080089 EXPECT_EQ(kContext, context);
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080090 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
91 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080092
93 EXPECT_EQ(0, c->Release(LocalHandle()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080094 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080095 EXPECT_EQ(0, c2->Discard());
96
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080097 EXPECT_EQ(1, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080098 EXPECT_EQ(0, p->Gain(&fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080099 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
100 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
101 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700102}
103
104TEST_F(LibBufferHubTest, TestEpoll) {
105 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
106 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
107 ASSERT_TRUE(p.get() != nullptr);
108 std::unique_ptr<BufferConsumer> c =
109 BufferConsumer::Import(p->CreateConsumer());
110 ASSERT_TRUE(c.get() != nullptr);
111
112 LocalHandle epoll_fd{epoll_create1(EPOLL_CLOEXEC)};
113 ASSERT_TRUE(epoll_fd.IsValid());
114
115 epoll_event event;
116 std::array<epoll_event, 64> events;
117
118 auto event_sources = p->GetEventSources();
119 ASSERT_LT(event_sources.size(), events.size());
120
121 for (const auto& event_source : event_sources) {
122 event = {.events = event_source.event_mask | EPOLLET,
123 .data = {.fd = p->event_fd()}};
124 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
125 &event));
126 }
127
128 event_sources = c->GetEventSources();
129 ASSERT_LT(event_sources.size(), events.size());
130
131 for (const auto& event_source : event_sources) {
132 event = {.events = event_source.event_mask | EPOLLET,
133 .data = {.fd = c->event_fd()}};
134 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
135 &event));
136 }
137
138 // No events should be signaled initially.
139 ASSERT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 0));
140
141 // Post the producer and check for consumer signal.
142 EXPECT_EQ(0, p->Post({}, kContext));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800143 ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
144 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700145 ASSERT_TRUE(events[0].events & EPOLLIN);
146 ASSERT_EQ(c->event_fd(), events[0].data.fd);
147
148 // Save the event bits to translate later.
149 event = events[0];
150
151 // Check for events again. Edge-triggered mode should prevent any.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800152 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));
158 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
159 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700160
161 // Translate the events.
162 auto event_status = c->GetEventMask(event.events);
163 ASSERT_TRUE(event_status);
164 ASSERT_TRUE(event_status.get() & EPOLLIN);
165
166 // Check for events again. Edge-triggered mode should prevent any.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800167 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
168 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700169}
170
171TEST_F(LibBufferHubTest, TestStateMask) {
172 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
173 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
174 ASSERT_TRUE(p.get() != nullptr);
175
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700176 // It's ok to create up to kMaxConsumerCount consumer buffers.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700177 uint64_t buffer_state_bits = p->buffer_state_bit();
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700178 std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
179 for (size_t i = 0; i < kMaxConsumerCount; i++) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700180 cs[i] = BufferConsumer::Import(p->CreateConsumer());
181 ASSERT_TRUE(cs[i].get() != nullptr);
182 // Expect all buffers have unique state mask.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800183 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700184 buffer_state_bits |= cs[i]->buffer_state_bit();
185 }
186 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
187
188 // The 64th creation will fail with out-of-memory error.
189 auto state = p->CreateConsumer();
190 EXPECT_EQ(state.error(), E2BIG);
191
192 // Release any consumer should allow us to re-create.
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700193 for (size_t i = 0; i < kMaxConsumerCount; i++) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700194 buffer_state_bits &= ~cs[i]->buffer_state_bit();
195 cs[i] = nullptr;
196 cs[i] = BufferConsumer::Import(p->CreateConsumer());
197 ASSERT_TRUE(cs[i].get() != nullptr);
198 // The released state mask will be reused.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800199 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700200 buffer_state_bits |= cs[i]->buffer_state_bit();
201 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
202 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800203}
204
Corey Tabakad53870c2017-07-06 18:04:27 -0700205TEST_F(LibBufferHubTest, TestStateTransitions) {
206 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
207 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
208 ASSERT_TRUE(p.get() != nullptr);
209 std::unique_ptr<BufferConsumer> c =
210 BufferConsumer::Import(p->CreateConsumer());
211 ASSERT_TRUE(c.get() != nullptr);
212
213 uint64_t context;
214 LocalHandle fence;
215
216 // The producer buffer starts in gained state.
217
218 // Acquire, release, and gain in gained state should fail.
219 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
220 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
221 EXPECT_EQ(-EALREADY, p->Gain(&fence));
222
223 // Post in gained state should succeed.
224 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
225
226 // Post, release, and gain in posted state should fail.
227 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
228 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
229 EXPECT_EQ(-EBUSY, p->Gain(&fence));
230
231 // Acquire in posted state should succeed.
232 EXPECT_LE(0, c->Acquire(&fence, &context));
233
234 // Acquire, post, and gain in acquired state should fail.
235 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
236 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
237 EXPECT_EQ(-EBUSY, p->Gain(&fence));
238
239 // Release in acquired state should succeed.
240 EXPECT_EQ(0, c->Release(LocalHandle()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800241 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabakad53870c2017-07-06 18:04:27 -0700242
243 // Release, acquire, and post in released state should fail.
244 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
245 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
246 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
247
248 // Gain in released state should succeed.
249 EXPECT_EQ(0, p->Gain(&fence));
250
251 // Acquire, release, and gain in gained state should fail.
252 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
253 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
254 EXPECT_EQ(-EALREADY, p->Gain(&fence));
255}
256
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700257TEST_F(LibBufferHubTest, TestAsyncStateTransitions) {
258 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
259 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
260 ASSERT_TRUE(p.get() != nullptr);
261 std::unique_ptr<BufferConsumer> c =
262 BufferConsumer::Import(p->CreateConsumer());
263 ASSERT_TRUE(c.get() != nullptr);
264
265 DvrNativeBufferMetadata metadata;
266 LocalHandle invalid_fence;
267
268 // The producer buffer starts in gained state.
269
270 // Acquire, release, and gain in gained state should fail.
271 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
272 EXPECT_FALSE(invalid_fence.IsValid());
273 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
274 EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
275 EXPECT_FALSE(invalid_fence.IsValid());
276
277 // Post in gained state should succeed.
278 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
279 EXPECT_EQ(p->buffer_state(), c->buffer_state());
280 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
281
282 // Post, release, and gain in posted state should fail.
283 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
284 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
285 EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
286 EXPECT_FALSE(invalid_fence.IsValid());
287
288 // Acquire in posted state should succeed.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800289 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700290 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
291 EXPECT_FALSE(invalid_fence.IsValid());
292 EXPECT_EQ(p->buffer_state(), c->buffer_state());
293 EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
294
295 // Acquire, post, and gain in acquired state should fail.
296 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
297 EXPECT_FALSE(invalid_fence.IsValid());
298 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
299 EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
300 EXPECT_FALSE(invalid_fence.IsValid());
301
302 // Release in acquired state should succeed.
303 EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800304 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700305 EXPECT_EQ(p->buffer_state(), c->buffer_state());
306 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
307
308 // Release, acquire, and post in released state should fail.
309 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
310 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
311 EXPECT_FALSE(invalid_fence.IsValid());
312 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
313
314 // Gain in released state should succeed.
315 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
316 EXPECT_FALSE(invalid_fence.IsValid());
317 EXPECT_EQ(p->buffer_state(), c->buffer_state());
318 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
319
320 // Acquire, release, and gain in gained state should fail.
321 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
322 EXPECT_FALSE(invalid_fence.IsValid());
323 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
324 EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
325 EXPECT_FALSE(invalid_fence.IsValid());
326}
327
328TEST_F(LibBufferHubTest, TestZeroConsumer) {
329 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
330 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
331 ASSERT_TRUE(p.get() != nullptr);
332
333 DvrNativeBufferMetadata metadata;
334 LocalHandle invalid_fence;
335
336 // Newly created.
337 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
338 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
339 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
340
341 // The buffer should stay in posted stay until a consumer picks it up.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800342 EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700343
344 // A new consumer should still be able to acquire the buffer immediately.
345 std::unique_ptr<BufferConsumer> c =
346 BufferConsumer::Import(p->CreateConsumer());
347 ASSERT_TRUE(c.get() != nullptr);
348 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
349 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
350}
351
352TEST_F(LibBufferHubTest, TestMaxConsumers) {
353 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
354 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
355 ASSERT_TRUE(p.get() != nullptr);
356
357 std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
358 for (size_t i = 0; i < kMaxConsumerCount; i++) {
359 cs[i] = BufferConsumer::Import(p->CreateConsumer());
360 ASSERT_TRUE(cs[i].get() != nullptr);
361 EXPECT_TRUE(IsBufferGained(cs[i]->buffer_state()));
362 }
363
364 DvrNativeBufferMetadata metadata;
365 LocalHandle invalid_fence;
366
367 // Post the producer should trigger all consumers to be available.
368 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
369 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
370 for (size_t i = 0; i < kMaxConsumerCount; i++) {
371 EXPECT_TRUE(IsBufferPosted(cs[i]->buffer_state(),
372 cs[i]->buffer_state_bit()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800373 EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700374 EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
375 EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
376 }
377
378 // All consumers have to release before the buffer is considered to be
379 // released.
380 for (size_t i = 0; i < kMaxConsumerCount; i++) {
381 EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
382 EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence));
383 }
384
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800385 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700386 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
387
388 // Buffer state cross all clients must be consistent.
389 for (size_t i = 0; i < kMaxConsumerCount; i++) {
390 EXPECT_EQ(p->buffer_state(), cs[i]->buffer_state());
391 }
392}
393
394TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) {
395 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
396 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
397 ASSERT_TRUE(p.get() != nullptr);
398 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
399
400 std::unique_ptr<BufferConsumer> c =
401 BufferConsumer::Import(p->CreateConsumer());
402 ASSERT_TRUE(c.get() != nullptr);
403 EXPECT_TRUE(IsBufferGained(c->buffer_state()));
404
405 DvrNativeBufferMetadata metadata;
406 LocalHandle invalid_fence;
407
408 // Post the gained buffer should signal already created consumer.
409 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
410 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800411 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700412 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
413 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
414}
415
416TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferPosted) {
417 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
418 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
419 ASSERT_TRUE(p.get() != nullptr);
420 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
421
422 DvrNativeBufferMetadata metadata;
423 LocalHandle invalid_fence;
424
425 // Post the gained buffer before any consumer gets created.
426 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
427 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
428
429 // Newly created consumer should be automatically sigalled.
430 std::unique_ptr<BufferConsumer> c =
431 BufferConsumer::Import(p->CreateConsumer());
432 ASSERT_TRUE(c.get() != nullptr);
433 EXPECT_TRUE(IsBufferPosted(c->buffer_state()));
434 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
435 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
436}
437
438TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
439 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
440 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
441 ASSERT_TRUE(p.get() != nullptr);
442
443 std::unique_ptr<BufferConsumer> c1 =
444 BufferConsumer::Import(p->CreateConsumer());
445 ASSERT_TRUE(c1.get() != nullptr);
446
447 DvrNativeBufferMetadata metadata;
448 LocalHandle invalid_fence;
449
450 // Post, acquire, and release the buffer..
451 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800452 EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700453 EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence));
454 EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence));
455
Jiwen 'Steve' Cai2d89e6b2017-12-06 16:32:22 -0800456 // Note that the next PDX call is on the producer channel, which may be
457 // executed before Release impulse gets executed by bufferhubd. Thus, here we
458 // need to wait until the releasd is confirmed before creating another
459 // consumer.
460 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
461 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
462
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700463 // Create another consumer immediately after the release, should not make the
Jiwen 'Steve' Cai2d89e6b2017-12-06 16:32:22 -0800464 // buffer un-released.
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700465 std::unique_ptr<BufferConsumer> c2 =
466 BufferConsumer::Import(p->CreateConsumer());
467 ASSERT_TRUE(c2.get() != nullptr);
468
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700469 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
470 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
471 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
472}
473
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800474TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
475 struct Metadata {
476 int64_t field1;
477 int64_t field2;
478 };
479 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
480 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
481 ASSERT_TRUE(p.get() != nullptr);
482 std::unique_ptr<BufferConsumer> c =
483 BufferConsumer::Import(p->CreateConsumer());
484 ASSERT_TRUE(c.get() != nullptr);
485
486 Metadata m = {1, 3};
487 EXPECT_EQ(0, p->Post(LocalHandle(), m));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800488 EXPECT_LE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800489
490 LocalHandle fence;
491 Metadata m2 = {};
492 EXPECT_EQ(0, c->Acquire(&fence, &m2));
493 EXPECT_EQ(m.field1, m2.field1);
494 EXPECT_EQ(m.field2, m2.field2);
495
496 EXPECT_EQ(0, c->Release(LocalHandle()));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800497 EXPECT_LT(0, RETRY_EINTR(p->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800498}
499
500TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
501 struct Metadata {
502 int64_t field1;
503 int64_t field2;
504 };
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700505 struct OverSizedMetadata {
506 int64_t field1;
507 int64_t field2;
508 int64_t field3;
509 };
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800510 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
511 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
512 ASSERT_TRUE(p.get() != nullptr);
513 std::unique_ptr<BufferConsumer> c =
514 BufferConsumer::Import(p->CreateConsumer());
515 ASSERT_TRUE(c.get() != nullptr);
516
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700517 // It is illegal to post metadata larger than originally requested during
518 // buffer allocation.
519 OverSizedMetadata evil_meta = {};
520 EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800521 EXPECT_GE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700522
523 // It is ok to post metadata smaller than originally requested during
524 // buffer allocation.
525 int64_t sequence = 42;
526 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800527}
528
529TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
530 struct Metadata {
531 int64_t field1;
532 int64_t field2;
533 };
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700534 struct OverSizedMetadata {
535 int64_t field1;
536 int64_t field2;
537 int64_t field3;
538 };
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800539 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
540 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
541 ASSERT_TRUE(p.get() != nullptr);
542 std::unique_ptr<BufferConsumer> c =
543 BufferConsumer::Import(p->CreateConsumer());
544 ASSERT_TRUE(c.get() != nullptr);
545
546 Metadata m = {1, 3};
547 EXPECT_EQ(0, p->Post(LocalHandle(), m));
548
549 LocalHandle fence;
550 int64_t sequence;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700551 OverSizedMetadata e;
552
553 // It is illegal to acquire metadata larger than originally requested during
554 // buffer allocation.
555 EXPECT_NE(0, c->Acquire(&fence, &e));
556
557 // It is ok to acquire metadata smaller than originally requested during
558 // buffer allocation.
559 EXPECT_EQ(0, c->Acquire(&fence, &sequence));
560 EXPECT_EQ(m.field1, sequence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800561}
562
563TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
564 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
565 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
566 ASSERT_TRUE(p.get() != nullptr);
567 std::unique_ptr<BufferConsumer> c =
568 BufferConsumer::Import(p->CreateConsumer());
569 ASSERT_TRUE(c.get() != nullptr);
570
571 int64_t sequence = 3;
572 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
573
574 LocalHandle fence;
575 EXPECT_EQ(0, c->Acquire(&fence));
576}
577
578TEST_F(LibBufferHubTest, TestWithNoMeta) {
579 std::unique_ptr<BufferProducer> p =
580 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
581 ASSERT_TRUE(p.get() != nullptr);
582 std::unique_ptr<BufferConsumer> c =
583 BufferConsumer::Import(p->CreateConsumer());
584 ASSERT_TRUE(c.get() != nullptr);
585
586 LocalHandle fence;
587
588 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
589 EXPECT_EQ(0, c->Acquire(&fence));
590}
591
592TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) {
593 std::unique_ptr<BufferProducer> p =
594 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
595 ASSERT_TRUE(p.get() != nullptr);
596 std::unique_ptr<BufferConsumer> c =
597 BufferConsumer::Import(p->CreateConsumer());
598 ASSERT_TRUE(c.get() != nullptr);
599
600 int64_t sequence = 3;
601 EXPECT_NE(0, p->Post(LocalHandle(), sequence));
602}
603
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700604namespace {
605
606int PollFd(int fd, int timeout_ms) {
607 pollfd p = {fd, POLLIN, 0};
608 return poll(&p, 1, timeout_ms);
609}
610
611} // namespace
612
613TEST_F(LibBufferHubTest, TestAcquireFence) {
614 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
615 kWidth, kHeight, kFormat, kUsage, /*metadata_size=*/0);
616 ASSERT_TRUE(p.get() != nullptr);
617 std::unique_ptr<BufferConsumer> c =
618 BufferConsumer::Import(p->CreateConsumer());
619 ASSERT_TRUE(c.get() != nullptr);
620
621 DvrNativeBufferMetadata meta;
622 LocalHandle f1(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
623
624 // Post with unsignaled fence.
625 EXPECT_EQ(0, p->PostAsync(&meta, f1));
626
627 // Should acquire a valid fence.
628 LocalHandle f2;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800629 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700630 EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
631 EXPECT_TRUE(f2.IsValid());
632 // The original fence and acquired fence should have different fd number.
633 EXPECT_NE(f1.Get(), f2.Get());
634 EXPECT_GE(0, PollFd(f2.Get(), 0));
635
636 // Signal the original fence will trigger the new fence.
637 eventfd_write(f1.Get(), 1);
638 // Now the original FD has been signaled.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800639 EXPECT_LT(0, PollFd(f2.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700640
641 // Release the consumer with an invalid fence.
642 EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
643
644 // Should gain an invalid fence.
645 LocalHandle f3;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800646 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700647 EXPECT_EQ(0, p->GainAsync(&meta, &f3));
648 EXPECT_FALSE(f3.IsValid());
649
650 // Post with a signaled fence.
651 EXPECT_EQ(0, p->PostAsync(&meta, f1));
652
653 // Should acquire a valid fence and it's already signalled.
654 LocalHandle f4;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800655 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700656 EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
657 EXPECT_TRUE(f4.IsValid());
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800658 EXPECT_LT(0, PollFd(f4.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700659
660 // Release with an unsignalled fence and signal it immediately after release
661 // without producer gainning.
662 LocalHandle f5(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
663 EXPECT_EQ(0, c->ReleaseAsync(&meta, f5));
664 eventfd_write(f5.Get(), 1);
665
666 // Should gain a valid fence, which is already signaled.
667 LocalHandle f6;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800668 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700669 EXPECT_EQ(0, p->GainAsync(&meta, &f6));
670 EXPECT_TRUE(f6.IsValid());
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800671 EXPECT_LT(0, PollFd(f6.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700672}
673
674TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
675 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
676 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
677 ASSERT_TRUE(p.get() != nullptr);
678 std::unique_ptr<BufferConsumer> c1 =
679 BufferConsumer::Import(p->CreateConsumer());
680 ASSERT_TRUE(c1.get() != nullptr);
681 const uint64_t consumer_state_bit1 = c1->buffer_state_bit();
682
683 DvrNativeBufferMetadata meta;
684 EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
685
686 LocalHandle fence;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800687 EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700688 EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
689 // Destroy the consumer now will make it orphaned and the buffer is still
690 // acquired.
691 c1 = nullptr;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800692 EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700693
694 std::unique_ptr<BufferConsumer> c2 =
695 BufferConsumer::Import(p->CreateConsumer());
696 ASSERT_TRUE(c2.get() != nullptr);
697 const uint64_t consumer_state_bit2 = c2->buffer_state_bit();
698 EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
699
700 // The new consumer is available for acquire.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800701 EXPECT_LT(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700702 EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
703 // Releasing the consumer makes the buffer gainable.
704 EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
705
706 // The buffer is now available for the producer to gain.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800707 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700708
709 // But if another consumer is created in released state.
710 std::unique_ptr<BufferConsumer> c3 =
711 BufferConsumer::Import(p->CreateConsumer());
712 ASSERT_TRUE(c3.get() != nullptr);
713 const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
714 EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
715 // The consumer buffer is not acquirable.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800716 EXPECT_GE(0, RETRY_EINTR(c3->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700717 EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
718
719 // Producer should be able to gain no matter what.
720 EXPECT_EQ(0, p->GainAsync(&meta, &fence));
721}
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700722
723TEST_F(LibBufferHubTest, TestDetachBufferFromProducer) {
724 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
725 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
726 std::unique_ptr<BufferConsumer> c =
727 BufferConsumer::Import(p->CreateConsumer());
728 ASSERT_TRUE(p.get() != nullptr);
729 ASSERT_TRUE(c.get() != nullptr);
730
731 DvrNativeBufferMetadata metadata;
732 LocalHandle invalid_fence;
733
734 // Detach in posted state should fail.
735 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
736 EXPECT_GT(RETRY_EINTR(c->Poll(kPollTimeoutMs)), 0);
737 auto s1 = p->Detach();
738 EXPECT_FALSE(s1);
739
740 // Detach in acquired state should fail.
741 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
742 s1 = p->Detach();
743 EXPECT_FALSE(s1);
744
745 // Detach in released state should fail.
746 EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
747 EXPECT_GT(RETRY_EINTR(p->Poll(kPollTimeoutMs)), 0);
748 s1 = p->Detach();
749 EXPECT_FALSE(s1);
750
751 // Detach in gained state should succeed.
752 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
753 s1 = p->Detach();
754 EXPECT_TRUE(s1);
755
756 LocalChannelHandle detached_buffer = s1.take();
757 EXPECT_TRUE(detached_buffer.valid());
758
759 // Both producer and consumer should have hangup.
760 EXPECT_GT(RETRY_EINTR(p->Poll(kPollTimeoutMs)), 0);
761 auto s2 = p->GetEventMask(POLLHUP);
762 EXPECT_TRUE(s2);
763 EXPECT_EQ(s2.get(), POLLHUP);
764
765 EXPECT_GT(RETRY_EINTR(c->Poll(kPollTimeoutMs)), 0);
766 s2 = p->GetEventMask(POLLHUP);
767 EXPECT_TRUE(s2);
768 EXPECT_EQ(s2.get(), POLLHUP);
769
770 auto s3 = p->CreateConsumer();
771 EXPECT_FALSE(s3);
Jiwen 'Steve' Caife924f32018-03-27 13:29:13 -0700772 // Note that here the expected error code is EOPNOTSUPP as the socket towards
773 // ProducerChannel has been teared down.
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700774 EXPECT_EQ(s3.error(), EOPNOTSUPP);
775
776 s3 = c->CreateConsumer();
777 EXPECT_FALSE(s3);
Jiwen 'Steve' Caife924f32018-03-27 13:29:13 -0700778 // Note that here the expected error code is EPIPE returned from
779 // ConsumerChannel::HandleMessage as the socket is still open but the producer
780 // is gone.
781 EXPECT_EQ(s3.error(), EPIPE);
Jiwen 'Steve' Cai23c1a732018-03-12 12:16:47 -0700782}