1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "mojo/core/core.h"
6 
7 #include <stdint.h>
8 
9 #include <limits>
10 
11 #include "base/bind.h"
12 #include "build/build_config.h"
13 #include "mojo/core/core_test_base.h"
14 #include "mojo/core/test_utils.h"
15 #include "mojo/public/cpp/system/wait.h"
16 
17 #if defined(OS_WIN)
18 #include "base/win/windows_version.h"
19 #endif
20 
21 namespace mojo {
22 namespace core {
23 namespace {
24 
25 const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u};
26 const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u};
27 const MojoHandleSignals kAllSignals =
28     MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
29     MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE |
30     MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED;
31 
32 using CoreTest = test::CoreTestBase;
33 
TEST_F(CoreTest,GetTimeTicksNow)34 TEST_F(CoreTest, GetTimeTicksNow) {
35   const MojoTimeTicks start = core()->GetTimeTicksNow();
36   ASSERT_NE(static_cast<MojoTimeTicks>(0), start)
37       << "GetTimeTicksNow should return nonzero value";
38   test::Sleep(test::DeadlineFromMilliseconds(15));
39   const MojoTimeTicks finish = core()->GetTimeTicksNow();
40   // Allow for some fuzz in sleep.
41   ASSERT_GE((finish - start), static_cast<MojoTimeTicks>(8000))
42       << "Sleeping should result in increasing time ticks";
43 }
44 
TEST_F(CoreTest,Basic)45 TEST_F(CoreTest, Basic) {
46   MockHandleInfo info;
47 
48   ASSERT_EQ(0u, info.GetCtorCallCount());
49   MojoHandle h = CreateMockHandle(&info);
50   ASSERT_EQ(1u, info.GetCtorCallCount());
51   ASSERT_NE(h, MOJO_HANDLE_INVALID);
52 
53   ASSERT_EQ(0u, info.GetWriteMessageCallCount());
54   MojoMessageHandle message;
55   ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message));
56   ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h, message, nullptr));
57   ASSERT_EQ(1u, info.GetWriteMessageCallCount());
58 
59   ASSERT_EQ(0u, info.GetReadMessageCallCount());
60   ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h, nullptr, &message));
61   ASSERT_EQ(1u, info.GetReadMessageCallCount());
62   ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h, nullptr, &message));
63   ASSERT_EQ(2u, info.GetReadMessageCallCount());
64 
65   ASSERT_EQ(0u, info.GetWriteDataCallCount());
66   ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED,
67             core()->WriteData(h, nullptr, nullptr, nullptr));
68   ASSERT_EQ(1u, info.GetWriteDataCallCount());
69 
70   ASSERT_EQ(0u, info.GetBeginWriteDataCallCount());
71   ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED,
72             core()->BeginWriteData(h, nullptr, nullptr, nullptr));
73   ASSERT_EQ(1u, info.GetBeginWriteDataCallCount());
74 
75   ASSERT_EQ(0u, info.GetEndWriteDataCallCount());
76   ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndWriteData(h, 0, nullptr));
77   ASSERT_EQ(1u, info.GetEndWriteDataCallCount());
78 
79   ASSERT_EQ(0u, info.GetReadDataCallCount());
80   ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED,
81             core()->ReadData(h, nullptr, nullptr, nullptr));
82   ASSERT_EQ(1u, info.GetReadDataCallCount());
83 
84   ASSERT_EQ(0u, info.GetBeginReadDataCallCount());
85   ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED,
86             core()->BeginReadData(h, nullptr, nullptr, nullptr));
87   ASSERT_EQ(1u, info.GetBeginReadDataCallCount());
88 
89   ASSERT_EQ(0u, info.GetEndReadDataCallCount());
90   ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0, nullptr));
91   ASSERT_EQ(1u, info.GetEndReadDataCallCount());
92 
93   ASSERT_EQ(0u, info.GetDtorCallCount());
94   ASSERT_EQ(0u, info.GetCloseCallCount());
95   ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h));
96   ASSERT_EQ(1u, info.GetCloseCallCount());
97   ASSERT_EQ(1u, info.GetDtorCallCount());
98 }
99 
TEST_F(CoreTest,InvalidArguments)100 TEST_F(CoreTest, InvalidArguments) {
101   // |Close()|:
102   {
103     ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(MOJO_HANDLE_INVALID));
104     ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(10));
105     ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(1000000000));
106 
107     // Test a double-close.
108     MockHandleInfo info;
109     MojoHandle h = CreateMockHandle(&info);
110     ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h));
111     ASSERT_EQ(1u, info.GetCloseCallCount());
112     ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h));
113     ASSERT_EQ(1u, info.GetCloseCallCount());
114   }
115 
116   // |CreateMessagePipe()|: Nothing to check (apart from things that cause
117   // death).
118 
119   // |WriteMessageNew()|:
120   // Only check arguments checked by |Core|, namely |handle|, |handles|, and
121   // |num_handles|.
122   ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
123             core()->WriteMessage(MOJO_HANDLE_INVALID, 0, nullptr));
124 
125   // |ReadMessageNew()|:
126   // Only check arguments checked by |Core|, namely |handle|, |handles|, and
127   // |num_handles|.
128   {
129     ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
130               core()->ReadMessage(MOJO_HANDLE_INVALID, nullptr, nullptr));
131 
132     MockHandleInfo info;
133     MojoHandle h = CreateMockHandle(&info);
134     ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
135               core()->ReadMessage(h, nullptr, nullptr));
136     // Checked by |Core|, shouldn't go through to the dispatcher.
137     ASSERT_EQ(0u, info.GetReadMessageCallCount());
138     ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h));
139   }
140 }
141 
TEST_F(CoreTest,MessagePipe)142 TEST_F(CoreTest, MessagePipe) {
143   MojoHandle h[2];
144   MojoHandleSignalsState hss[2];
145 
146   ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessagePipe(nullptr, &h[0], &h[1]));
147   // Should get two distinct, valid handles.
148   ASSERT_NE(h[0], MOJO_HANDLE_INVALID);
149   ASSERT_NE(h[1], MOJO_HANDLE_INVALID);
150   ASSERT_NE(h[0], h[1]);
151 
152   // Neither should be readable.
153   hss[0] = kEmptyMojoHandleSignalsState;
154   hss[1] = kEmptyMojoHandleSignalsState;
155   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[0], &hss[0]));
156   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[1], &hss[1]));
157   ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
158   ASSERT_EQ(kAllSignals, hss[0].satisfiable_signals);
159   ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
160   ASSERT_EQ(kAllSignals, hss[1].satisfiable_signals);
161 
162   // Try to read anyway.
163   MojoMessageHandle message;
164   ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT,
165             core()->ReadMessage(h[0], nullptr, &message));
166 
167   // Write to |h[1]|.
168   const uintptr_t kTestMessageContext = 123;
169   ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message));
170   ASSERT_EQ(MOJO_RESULT_OK,
171             core()->SetMessageContext(message, kTestMessageContext, nullptr,
172                                       nullptr, nullptr));
173   ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h[1], message, nullptr));
174 
175   // Wait for |h[0]| to become readable.
176   EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h[0]),
177                                        MOJO_HANDLE_SIGNAL_READABLE, &hss[0]));
178 
179   // Read from |h[0]|.
180   ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h[0], nullptr, &message));
181   uintptr_t context;
182   ASSERT_EQ(MOJO_RESULT_OK,
183             core()->GetMessageContext(message, nullptr, &context));
184   ASSERT_EQ(MOJO_RESULT_OK,
185             core()->SetMessageContext(message, 0, nullptr, nullptr, nullptr));
186   ASSERT_EQ(kTestMessageContext, context);
187   ASSERT_EQ(MOJO_RESULT_OK, core()->DestroyMessage(message));
188 
189   // |h[0]| should no longer be readable.
190   hss[0] = kEmptyMojoHandleSignalsState;
191   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[0], &hss[0]));
192   ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
193   ASSERT_EQ(kAllSignals, hss[0].satisfiable_signals);
194 
195   // Write to |h[0]|.
196   ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message));
197   ASSERT_EQ(MOJO_RESULT_OK,
198             core()->SetMessageContext(message, kTestMessageContext, nullptr,
199                                       nullptr, nullptr));
200   ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h[0], message, nullptr));
201 
202   // Close |h[0]|.
203   ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h[0]));
204 
205   // Wait for |h[1]| to learn about the other end's closure.
206   EXPECT_EQ(
207       MOJO_RESULT_OK,
208       mojo::Wait(mojo::Handle(h[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss[1]));
209 
210   // Check that |h[1]| is no longer writable (and will never be).
211   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
212             hss[1].satisfied_signals);
213   EXPECT_FALSE(hss[1].satisfiable_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
214 
215   // Check that |h[1]| is still readable (for the moment).
216   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
217             hss[1].satisfied_signals);
218   EXPECT_TRUE(hss[1].satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
219 
220   // Discard a message from |h[1]|.
221   ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h[1], nullptr, &message));
222   ASSERT_EQ(MOJO_RESULT_OK, core()->DestroyMessage(message));
223 
224   // |h[1]| is no longer readable (and will never be).
225   hss[1] = kFullMojoHandleSignalsState;
226   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[1], &hss[1]));
227   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[1].satisfied_signals);
228   EXPECT_FALSE(hss[1].satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
229 
230   // Try writing to |h[1]|.
231   ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message));
232   ASSERT_EQ(MOJO_RESULT_OK,
233             core()->SetMessageContext(message, kTestMessageContext, nullptr,
234                                       nullptr, nullptr));
235   ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
236             core()->WriteMessage(h[1], message, nullptr));
237 
238   ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h[1]));
239 }
240 
241 // Tests passing a message pipe handle.
TEST_F(CoreTest,MessagePipeBasicLocalHandlePassing1)242 TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
243   MojoHandleSignalsState hss;
244   MojoHandle h_passing[2];
245   ASSERT_EQ(MOJO_RESULT_OK,
246             core()->CreateMessagePipe(nullptr, &h_passing[0], &h_passing[1]));
247 
248   // Make sure that |h_passing[]| work properly.
249   const uintptr_t kTestMessageContext = 42;
250   MojoMessageHandle message;
251   ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message));
252   ASSERT_EQ(MOJO_RESULT_OK,
253             core()->SetMessageContext(message, kTestMessageContext, nullptr,
254                                       nullptr, nullptr));
255   ASSERT_EQ(MOJO_RESULT_OK,
256             core()->WriteMessage(h_passing[0], message, nullptr));
257   hss = kEmptyMojoHandleSignalsState;
258   EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]),
259                                        MOJO_HANDLE_SIGNAL_READABLE, &hss));
260   ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
261             hss.satisfied_signals);
262   ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
263   MojoMessageHandle message_handle;
264   ASSERT_EQ(MOJO_RESULT_OK,
265             core()->ReadMessage(h_passing[1], nullptr, &message_handle));
266   uintptr_t context;
267   ASSERT_EQ(MOJO_RESULT_OK,
268             core()->GetMessageContext(message_handle, nullptr, &context));
269   ASSERT_EQ(MOJO_RESULT_OK,
270             core()->SetMessageContext(message, 0, nullptr, nullptr, nullptr));
271   ASSERT_EQ(kTestMessageContext, context);
272   ASSERT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
273 
274   ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0]));
275   ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1]));
276 }
277 
TEST_F(CoreTest,DataPipe)278 TEST_F(CoreTest, DataPipe) {
279   MojoHandle ph, ch;  // p is for producer and c is for consumer.
280   MojoHandleSignalsState hss;
281 
282   ASSERT_EQ(MOJO_RESULT_OK, core()->CreateDataPipe(nullptr, &ph, &ch));
283   // Should get two distinct, valid handles.
284   ASSERT_NE(ph, MOJO_HANDLE_INVALID);
285   ASSERT_NE(ch, MOJO_HANDLE_INVALID);
286   ASSERT_NE(ph, ch);
287 
288   // Producer should be never-readable, but already writable.
289   hss = kEmptyMojoHandleSignalsState;
290   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ph, &hss));
291   ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
292   ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
293                 MOJO_HANDLE_SIGNAL_PEER_REMOTE,
294             hss.satisfiable_signals);
295 
296   // Consumer should be never-writable, and not yet readable.
297   hss = kFullMojoHandleSignalsState;
298   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ch, &hss));
299   EXPECT_EQ(0u, hss.satisfied_signals);
300   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
301                 MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE |
302                 MOJO_HANDLE_SIGNAL_PEER_REMOTE,
303             hss.satisfiable_signals);
304 
305   // Write.
306   signed char elements[2] = {'A', 'B'};
307   uint32_t num_bytes = 2u;
308   ASSERT_EQ(MOJO_RESULT_OK,
309             core()->WriteData(ph, elements, &num_bytes, nullptr));
310   ASSERT_EQ(2u, num_bytes);
311 
312   // Wait for the data to arrive to the consumer.
313   EXPECT_EQ(MOJO_RESULT_OK,
314             mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_READABLE, &hss));
315 
316   // Consumer should now be readable.
317   hss = kEmptyMojoHandleSignalsState;
318   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ch, &hss));
319   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE,
320             hss.satisfied_signals);
321   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
322                 MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE |
323                 MOJO_HANDLE_SIGNAL_PEER_REMOTE,
324             hss.satisfiable_signals);
325 
326   // Peek one character.
327   elements[0] = -1;
328   elements[1] = -1;
329   num_bytes = 1u;
330   MojoReadDataOptions read_options;
331   read_options.struct_size = sizeof(read_options);
332   read_options.flags = MOJO_READ_DATA_FLAG_NONE | MOJO_READ_DATA_FLAG_PEEK;
333   ASSERT_EQ(MOJO_RESULT_OK,
334             core()->ReadData(ch, &read_options, elements, &num_bytes));
335   ASSERT_EQ('A', elements[0]);
336   ASSERT_EQ(-1, elements[1]);
337 
338   // Read one character.
339   elements[0] = -1;
340   elements[1] = -1;
341   num_bytes = 1u;
342   read_options.flags = MOJO_READ_DATA_FLAG_NONE;
343   ASSERT_EQ(MOJO_RESULT_OK,
344             core()->ReadData(ch, &read_options, elements, &num_bytes));
345   ASSERT_EQ('A', elements[0]);
346   ASSERT_EQ(-1, elements[1]);
347 
348   // Two-phase write.
349   void* write_ptr = nullptr;
350   num_bytes = 0u;
351   ASSERT_EQ(MOJO_RESULT_OK,
352             core()->BeginWriteData(ph, nullptr, &write_ptr, &num_bytes));
353   // We count on the default options providing a decent buffer size.
354   ASSERT_GE(num_bytes, 3u);
355 
356   // Trying to do a normal write during a two-phase write should fail.
357   elements[0] = 'X';
358   num_bytes = 1u;
359   ASSERT_EQ(MOJO_RESULT_BUSY,
360             core()->WriteData(ph, elements, &num_bytes, nullptr));
361 
362   // Actually write the data, and complete it now.
363   static_cast<char*>(write_ptr)[0] = 'C';
364   static_cast<char*>(write_ptr)[1] = 'D';
365   static_cast<char*>(write_ptr)[2] = 'E';
366   ASSERT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 3u, nullptr));
367 
368   // Wait for the data to arrive to the consumer.
369   ASSERT_EQ(MOJO_RESULT_OK,
370             mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_READABLE, &hss));
371 
372   // Query how much data we have.
373   num_bytes = 0;
374   read_options.flags = MOJO_READ_DATA_FLAG_QUERY;
375   ASSERT_EQ(MOJO_RESULT_OK,
376             core()->ReadData(ch, &read_options, nullptr, &num_bytes));
377   ASSERT_GE(num_bytes, 1u);
378 
379   // Try to query with peek. Should fail.
380   num_bytes = 0;
381   read_options.flags = MOJO_READ_DATA_FLAG_QUERY | MOJO_READ_DATA_FLAG_PEEK;
382   ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
383             core()->ReadData(ch, &read_options, nullptr, &num_bytes));
384   ASSERT_EQ(0u, num_bytes);
385 
386   // Try to discard ten characters, in all-or-none mode. Should fail.
387   num_bytes = 10;
388   read_options.flags =
389       MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE;
390   ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE,
391             core()->ReadData(ch, &read_options, nullptr, &num_bytes));
392 
393   // Try to discard two characters, in peek mode. Should fail.
394   num_bytes = 2;
395   read_options.flags = MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_PEEK;
396   ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
397             core()->ReadData(ch, &read_options, nullptr, &num_bytes));
398 
399   // Discard a character.
400   num_bytes = 1;
401   read_options.flags =
402       MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE;
403   ASSERT_EQ(MOJO_RESULT_OK,
404             core()->ReadData(ch, &read_options, nullptr, &num_bytes));
405 
406   // Ensure the 3 bytes were read.
407   ASSERT_EQ(MOJO_RESULT_OK,
408             mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_READABLE, &hss));
409 
410   // Read the remaining three characters, in two-phase mode.
411   const void* read_ptr = nullptr;
412   num_bytes = 3;
413   ASSERT_EQ(MOJO_RESULT_OK,
414             core()->BeginReadData(ch, nullptr, &read_ptr, &num_bytes));
415   // Note: Count on still being able to do the contiguous read here.
416   ASSERT_EQ(3u, num_bytes);
417 
418   // Discarding right now should fail.
419   num_bytes = 1;
420   read_options.flags = MOJO_READ_DATA_FLAG_DISCARD;
421   ASSERT_EQ(MOJO_RESULT_BUSY,
422             core()->ReadData(ch, &read_options, nullptr, &num_bytes));
423 
424   // Actually check our data and end the two-phase read.
425   ASSERT_EQ('C', static_cast<const char*>(read_ptr)[0]);
426   ASSERT_EQ('D', static_cast<const char*>(read_ptr)[1]);
427   ASSERT_EQ('E', static_cast<const char*>(read_ptr)[2]);
428   ASSERT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 3u, nullptr));
429 
430   // Consumer should now be no longer readable.
431   hss = kFullMojoHandleSignalsState;
432   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ch, &hss));
433   EXPECT_EQ(0u, hss.satisfied_signals);
434   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
435                 MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE |
436                 MOJO_HANDLE_SIGNAL_PEER_REMOTE,
437             hss.satisfiable_signals);
438 
439   // TODO(vtl): More.
440 
441   // Close the producer.
442   ASSERT_EQ(MOJO_RESULT_OK, core()->Close(ph));
443 
444   // Wait for this to get to the consumer.
445   EXPECT_EQ(MOJO_RESULT_OK,
446             mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss));
447 
448   // The consumer should now be never-readable.
449   hss = kFullMojoHandleSignalsState;
450   EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ch, &hss));
451   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
452   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
453 
454   ASSERT_EQ(MOJO_RESULT_OK, core()->Close(ch));
455 }
456 
457 }  // namespace
458 }  // namespace core
459 }  // namespace mojo
460