• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 package org.chromium.mojo.system.impl;
6 
7 import android.test.suitebuilder.annotation.SmallTest;
8 
9 import org.chromium.mojo.MojoTestCase;
10 import org.chromium.mojo.system.AsyncWaiter;
11 import org.chromium.mojo.system.AsyncWaiter.Callback;
12 import org.chromium.mojo.system.AsyncWaiter.Cancellable;
13 import org.chromium.mojo.system.Core;
14 import org.chromium.mojo.system.Core.HandleSignals;
15 import org.chromium.mojo.system.Core.HandleSignalsState;
16 import org.chromium.mojo.system.Core.WaitManyResult;
17 import org.chromium.mojo.system.Core.WaitResult;
18 import org.chromium.mojo.system.DataPipe;
19 import org.chromium.mojo.system.Handle;
20 import org.chromium.mojo.system.InvalidHandle;
21 import org.chromium.mojo.system.MessagePipeHandle;
22 import org.chromium.mojo.system.MojoException;
23 import org.chromium.mojo.system.MojoResult;
24 import org.chromium.mojo.system.Pair;
25 import org.chromium.mojo.system.ResultAnd;
26 import org.chromium.mojo.system.SharedBufferHandle;
27 
28 import java.nio.ByteBuffer;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.Random;
34 import java.util.concurrent.Executors;
35 import java.util.concurrent.ScheduledExecutorService;
36 import java.util.concurrent.TimeUnit;
37 
38 /**
39  * Testing the core API.
40  */
41 public class CoreImplTest extends MojoTestCase {
42     private static final long RUN_LOOP_TIMEOUT_MS = 5;
43 
44     private static final ScheduledExecutorService WORKER =
45             Executors.newSingleThreadScheduledExecutor();
46 
47     private static final HandleSignals ALL_SIGNALS =
48             HandleSignals.none().setPeerClosed(true).setReadable(true).setWritable(true);
49 
50     private List<Handle> mHandlesToClose = new ArrayList<Handle>();
51 
52     /**
53      * @see MojoTestCase#tearDown()
54      */
55     @Override
tearDown()56     protected void tearDown() throws Exception {
57         MojoException toThrow = null;
58         for (Handle handle : mHandlesToClose) {
59             try {
60                 handle.close();
61             } catch (MojoException e) {
62                 if (toThrow == null) {
63                     toThrow = e;
64                 }
65             }
66         }
67         if (toThrow != null) {
68             throw toThrow;
69         }
70         super.tearDown();
71     }
72 
addHandleToClose(Handle handle)73     private void addHandleToClose(Handle handle) {
74         mHandlesToClose.add(handle);
75     }
76 
addHandlePairToClose(Pair<? extends Handle, ? extends Handle> handles)77     private void addHandlePairToClose(Pair<? extends Handle, ? extends Handle> handles) {
78         mHandlesToClose.add(handles.first);
79         mHandlesToClose.add(handles.second);
80     }
81 
82     /**
83      * Runnable that will close the given handle.
84      */
85     private static class CloseHandle implements Runnable {
86         private Handle mHandle;
87 
CloseHandle(Handle handle)88         CloseHandle(Handle handle) {
89             mHandle = handle;
90         }
91 
92         @Override
run()93         public void run() {
94             mHandle.close();
95         }
96     }
97 
checkSendingMessage(MessagePipeHandle in, MessagePipeHandle out)98     private static void checkSendingMessage(MessagePipeHandle in, MessagePipeHandle out) {
99         Random random = new Random();
100 
101         // Writing a random 8 bytes message.
102         byte[] bytes = new byte[8];
103         random.nextBytes(bytes);
104         ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
105         buffer.put(bytes);
106         in.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.NONE);
107 
108         // Try to read into a small buffer.
109         ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length / 2);
110         ResultAnd<MessagePipeHandle.ReadMessageResult> result =
111                 out.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE);
112         assertEquals(MojoResult.RESOURCE_EXHAUSTED, result.getMojoResult());
113         assertEquals(bytes.length, result.getValue().getMessageSize());
114         assertEquals(0, result.getValue().getHandlesCount());
115 
116         // Read into a correct buffer.
117         receiveBuffer = ByteBuffer.allocateDirect(bytes.length);
118         result = out.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE);
119         assertEquals(MojoResult.OK, result.getMojoResult());
120         assertEquals(bytes.length, result.getValue().getMessageSize());
121         assertEquals(0, result.getValue().getHandlesCount());
122         assertEquals(0, receiveBuffer.position());
123         assertEquals(result.getValue().getMessageSize(), receiveBuffer.limit());
124         byte[] receivedBytes = new byte[result.getValue().getMessageSize()];
125         receiveBuffer.get(receivedBytes);
126         assertTrue(Arrays.equals(bytes, receivedBytes));
127     }
128 
checkSendingData(DataPipe.ProducerHandle in, DataPipe.ConsumerHandle out)129     private static void checkSendingData(DataPipe.ProducerHandle in, DataPipe.ConsumerHandle out) {
130         Random random = new Random();
131 
132         // Writing a random 8 bytes message.
133         byte[] bytes = new byte[8];
134         random.nextBytes(bytes);
135         ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
136         buffer.put(bytes);
137         ResultAnd<Integer> result = in.writeData(buffer, DataPipe.WriteFlags.NONE);
138         assertEquals(MojoResult.OK, result.getMojoResult());
139         assertEquals(bytes.length, result.getValue().intValue());
140 
141         // Query number of bytes available.
142         ResultAnd<Integer> readResult = out.readData(null, DataPipe.ReadFlags.none().query(true));
143         assertEquals(MojoResult.OK, readResult.getMojoResult());
144         assertEquals(bytes.length, readResult.getValue().intValue());
145 
146         // Peek data into a buffer.
147         ByteBuffer peekBuffer = ByteBuffer.allocateDirect(bytes.length);
148         readResult = out.readData(peekBuffer, DataPipe.ReadFlags.none().peek(true));
149         assertEquals(MojoResult.OK, readResult.getMojoResult());
150         assertEquals(bytes.length, readResult.getValue().intValue());
151         assertEquals(bytes.length, peekBuffer.limit());
152         byte[] peekBytes = new byte[bytes.length];
153         peekBuffer.get(peekBytes);
154         assertTrue(Arrays.equals(bytes, peekBytes));
155 
156         // Read into a buffer.
157         ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length);
158         readResult = out.readData(receiveBuffer, DataPipe.ReadFlags.NONE);
159         assertEquals(MojoResult.OK, readResult.getMojoResult());
160         assertEquals(bytes.length, readResult.getValue().intValue());
161         assertEquals(0, receiveBuffer.position());
162         assertEquals(bytes.length, receiveBuffer.limit());
163         byte[] receivedBytes = new byte[bytes.length];
164         receiveBuffer.get(receivedBytes);
165         assertTrue(Arrays.equals(bytes, receivedBytes));
166     }
167 
checkSharing(SharedBufferHandle in, SharedBufferHandle out)168     private static void checkSharing(SharedBufferHandle in, SharedBufferHandle out) {
169         Random random = new Random();
170 
171         ByteBuffer buffer1 = in.map(0, 8, SharedBufferHandle.MapFlags.NONE);
172         assertEquals(8, buffer1.capacity());
173         ByteBuffer buffer2 = out.map(0, 8, SharedBufferHandle.MapFlags.NONE);
174         assertEquals(8, buffer2.capacity());
175 
176         byte[] bytes = new byte[8];
177         random.nextBytes(bytes);
178         buffer1.put(bytes);
179 
180         byte[] receivedBytes = new byte[bytes.length];
181         buffer2.get(receivedBytes);
182 
183         assertTrue(Arrays.equals(bytes, receivedBytes));
184 
185         in.unmap(buffer1);
186         out.unmap(buffer2);
187     }
188 
189     /**
190      * Testing {@link Core#waitMany(List, long)}.
191      */
192     @SmallTest
testWaitMany()193     public void testWaitMany() {
194         Core core = CoreImpl.getInstance();
195         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
196         addHandlePairToClose(handles);
197 
198         // Test waiting on handles of a newly created message pipe - each should be writable, but
199         // not readable.
200         List<Pair<Handle, Core.HandleSignals>> handlesToWaitOn =
201                 new ArrayList<Pair<Handle, Core.HandleSignals>>();
202         handlesToWaitOn.add(
203                 new Pair<Handle, Core.HandleSignals>(handles.second, Core.HandleSignals.READABLE));
204         handlesToWaitOn.add(
205                 new Pair<Handle, Core.HandleSignals>(handles.first, Core.HandleSignals.WRITABLE));
206         WaitManyResult result = core.waitMany(handlesToWaitOn, 0);
207         assertEquals(MojoResult.OK, result.getMojoResult());
208         assertEquals(1, result.getHandleIndex());
209         for (HandleSignalsState state : result.getSignalStates()) {
210             assertEquals(HandleSignals.WRITABLE, state.getSatisfiedSignals());
211             assertEquals(ALL_SIGNALS, state.getSatisfiableSignals());
212         }
213 
214         // Same test, but swap the handles around.
215         handlesToWaitOn.clear();
216         handlesToWaitOn.add(
217                 new Pair<Handle, Core.HandleSignals>(handles.first, Core.HandleSignals.WRITABLE));
218         handlesToWaitOn.add(
219                 new Pair<Handle, Core.HandleSignals>(handles.second, Core.HandleSignals.READABLE));
220         result = core.waitMany(handlesToWaitOn, 0);
221         assertEquals(MojoResult.OK, result.getMojoResult());
222         assertEquals(0, result.getHandleIndex());
223         for (HandleSignalsState state : result.getSignalStates()) {
224             assertEquals(HandleSignals.WRITABLE, state.getSatisfiedSignals());
225             assertEquals(ALL_SIGNALS, state.getSatisfiableSignals());
226         }
227     }
228 
229     /**
230      * Testing that Core can be retrieved from a handle.
231      */
232     @SmallTest
testGetCore()233     public void testGetCore() {
234         Core core = CoreImpl.getInstance();
235 
236         Pair<? extends Handle, ? extends Handle> handles = core.createMessagePipe(null);
237         addHandlePairToClose(handles);
238         assertEquals(core, handles.first.getCore());
239         assertEquals(core, handles.second.getCore());
240 
241         handles = core.createDataPipe(null);
242         addHandlePairToClose(handles);
243         assertEquals(core, handles.first.getCore());
244         assertEquals(core, handles.second.getCore());
245 
246         SharedBufferHandle handle = core.createSharedBuffer(null, 100);
247         SharedBufferHandle handle2 = handle.duplicate(null);
248         addHandleToClose(handle);
249         addHandleToClose(handle2);
250         assertEquals(core, handle.getCore());
251         assertEquals(core, handle2.getCore());
252     }
253 
createAndCloseMessagePipe(MessagePipeHandle.CreateOptions options)254     private static void createAndCloseMessagePipe(MessagePipeHandle.CreateOptions options) {
255         Core core = CoreImpl.getInstance();
256         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(options);
257         handles.first.close();
258         handles.second.close();
259     }
260 
261     /**
262      * Testing {@link MessagePipeHandle} creation.
263      */
264     @SmallTest
testMessagePipeCreation()265     public void testMessagePipeCreation() {
266         // Test creation with null options.
267         createAndCloseMessagePipe(null);
268         // Test creation with default options.
269         createAndCloseMessagePipe(new MessagePipeHandle.CreateOptions());
270     }
271 
272     /**
273      * Testing {@link MessagePipeHandle}.
274      */
275     @SmallTest
testMessagePipeEmpty()276     public void testMessagePipeEmpty() {
277         Core core = CoreImpl.getInstance();
278         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
279         addHandlePairToClose(handles);
280         // Test waiting on handles of a newly created message pipe.
281         WaitResult waitResult = handles.first.wait(
282                 Core.HandleSignals.none().setReadable(true).setWritable(true), 0);
283         assertEquals(MojoResult.OK, waitResult.getMojoResult());
284         assertEquals(
285                 HandleSignals.WRITABLE, waitResult.getHandleSignalsState().getSatisfiedSignals());
286         assertEquals(ALL_SIGNALS, waitResult.getHandleSignalsState().getSatisfiableSignals());
287 
288         waitResult = handles.first.wait(Core.HandleSignals.WRITABLE, 0);
289         assertEquals(MojoResult.OK, waitResult.getMojoResult());
290         assertEquals(
291                 HandleSignals.WRITABLE, waitResult.getHandleSignalsState().getSatisfiedSignals());
292         assertEquals(ALL_SIGNALS, waitResult.getHandleSignalsState().getSatisfiableSignals());
293 
294         waitResult = handles.first.wait(Core.HandleSignals.READABLE, 0);
295         assertEquals(MojoResult.DEADLINE_EXCEEDED, waitResult.getMojoResult());
296         assertEquals(
297                 HandleSignals.WRITABLE, waitResult.getHandleSignalsState().getSatisfiedSignals());
298         assertEquals(ALL_SIGNALS, waitResult.getHandleSignalsState().getSatisfiableSignals());
299 
300         // Testing read on an empty pipe.
301         ResultAnd<MessagePipeHandle.ReadMessageResult> readResult =
302                 handles.first.readMessage(null, 0, MessagePipeHandle.ReadFlags.NONE);
303         assertEquals(MojoResult.SHOULD_WAIT, readResult.getMojoResult());
304 
305         // Closing a pipe while waiting.
306         WORKER.schedule(new CloseHandle(handles.first), 10, TimeUnit.MILLISECONDS);
307         waitResult = handles.first.wait(Core.HandleSignals.READABLE, 1000000L);
308         assertEquals(MojoResult.CANCELLED, waitResult.getMojoResult());
309         assertEquals(
310                 HandleSignals.none(), waitResult.getHandleSignalsState().getSatisfiedSignals());
311         assertEquals(
312                 HandleSignals.none(), waitResult.getHandleSignalsState().getSatisfiableSignals());
313 
314         handles = core.createMessagePipe(null);
315         addHandlePairToClose(handles);
316 
317         // Closing the other pipe while waiting.
318         WORKER.schedule(new CloseHandle(handles.first), 10, TimeUnit.MILLISECONDS);
319         waitResult = handles.second.wait(Core.HandleSignals.READABLE, 1000000L);
320         assertEquals(MojoResult.FAILED_PRECONDITION, waitResult.getMojoResult());
321 
322         // Waiting on a closed pipe.
323         waitResult = handles.second.wait(Core.HandleSignals.READABLE, 0);
324         assertEquals(MojoResult.FAILED_PRECONDITION, waitResult.getMojoResult());
325         waitResult = handles.second.wait(Core.HandleSignals.WRITABLE, 0);
326         assertEquals(MojoResult.FAILED_PRECONDITION, waitResult.getMojoResult());
327     }
328 
329     /**
330      * Testing {@link MessagePipeHandle}.
331      */
332     @SmallTest
testMessagePipeSend()333     public void testMessagePipeSend() {
334         Core core = CoreImpl.getInstance();
335         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
336         addHandlePairToClose(handles);
337 
338         checkSendingMessage(handles.first, handles.second);
339         checkSendingMessage(handles.second, handles.first);
340     }
341 
342     /**
343      * Testing {@link MessagePipeHandle}.
344      */
345     @SmallTest
testMessagePipeReceiveOnSmallBuffer()346     public void testMessagePipeReceiveOnSmallBuffer() {
347         Random random = new Random();
348         Core core = CoreImpl.getInstance();
349         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
350         addHandlePairToClose(handles);
351 
352         // Writing a random 8 bytes message.
353         byte[] bytes = new byte[8];
354         random.nextBytes(bytes);
355         ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
356         buffer.put(bytes);
357         handles.first.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.NONE);
358 
359         ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(1);
360         ResultAnd<MessagePipeHandle.ReadMessageResult> result =
361                 handles.second.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE);
362         assertEquals(MojoResult.RESOURCE_EXHAUSTED, result.getMojoResult());
363         assertEquals(bytes.length, result.getValue().getMessageSize());
364         assertEquals(0, result.getValue().getHandlesCount());
365     }
366 
367     /**
368      * Testing {@link MessagePipeHandle}.
369      */
370     @SmallTest
testMessagePipeSendHandles()371     public void testMessagePipeSendHandles() {
372         Core core = CoreImpl.getInstance();
373         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
374         Pair<MessagePipeHandle, MessagePipeHandle> handlesToShare = core.createMessagePipe(null);
375         addHandlePairToClose(handles);
376         addHandlePairToClose(handlesToShare);
377 
378         handles.first.writeMessage(null, Collections.<Handle>singletonList(handlesToShare.second),
379                 MessagePipeHandle.WriteFlags.NONE);
380         assertFalse(handlesToShare.second.isValid());
381         ResultAnd<MessagePipeHandle.ReadMessageResult> readMessageResult =
382                 handles.second.readMessage(null, 1, MessagePipeHandle.ReadFlags.NONE);
383         assertEquals(1, readMessageResult.getValue().getHandlesCount());
384         MessagePipeHandle newHandle =
385                 readMessageResult.getValue().getHandles().get(0).toMessagePipeHandle();
386         addHandleToClose(newHandle);
387         assertTrue(newHandle.isValid());
388         checkSendingMessage(handlesToShare.first, newHandle);
389         checkSendingMessage(newHandle, handlesToShare.first);
390     }
391 
createAndCloseDataPipe(DataPipe.CreateOptions options)392     private static void createAndCloseDataPipe(DataPipe.CreateOptions options) {
393         Core core = CoreImpl.getInstance();
394         Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles =
395                 core.createDataPipe(options);
396         handles.first.close();
397         handles.second.close();
398     }
399 
400     /**
401      * Testing {@link DataPipe}.
402      */
403     @SmallTest
testDataPipeCreation()404     public void testDataPipeCreation() {
405         // Create datapipe with null options.
406         createAndCloseDataPipe(null);
407         DataPipe.CreateOptions options = new DataPipe.CreateOptions();
408         // Create datapipe with element size set.
409         options.setElementNumBytes(24);
410         createAndCloseDataPipe(options);
411         // Create datapipe with capacity set.
412         options.setCapacityNumBytes(1024 * options.getElementNumBytes());
413         createAndCloseDataPipe(options);
414     }
415 
416     /**
417      * Testing {@link DataPipe}.
418      */
419     @SmallTest
testDataPipeSend()420     public void testDataPipeSend() {
421         Core core = CoreImpl.getInstance();
422 
423         Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
424         addHandlePairToClose(handles);
425 
426         checkSendingData(handles.first, handles.second);
427     }
428 
429     /**
430      * Testing {@link DataPipe}.
431      */
432     @SmallTest
testDataPipeTwoPhaseSend()433     public void testDataPipeTwoPhaseSend() {
434         Random random = new Random();
435         Core core = CoreImpl.getInstance();
436         Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
437         addHandlePairToClose(handles);
438 
439         // Writing a random 8 bytes message.
440         byte[] bytes = new byte[8];
441         random.nextBytes(bytes);
442         ByteBuffer buffer = handles.first.beginWriteData(bytes.length, DataPipe.WriteFlags.NONE);
443         assertTrue(buffer.capacity() >= bytes.length);
444         buffer.put(bytes);
445         handles.first.endWriteData(bytes.length);
446 
447         // Read into a buffer.
448         ByteBuffer receiveBuffer =
449                 handles.second.beginReadData(bytes.length, DataPipe.ReadFlags.NONE);
450         assertEquals(0, receiveBuffer.position());
451         assertEquals(bytes.length, receiveBuffer.limit());
452         byte[] receivedBytes = new byte[bytes.length];
453         receiveBuffer.get(receivedBytes);
454         assertTrue(Arrays.equals(bytes, receivedBytes));
455         handles.second.endReadData(bytes.length);
456     }
457 
458     /**
459      * Testing {@link DataPipe}.
460      */
461     @SmallTest
testDataPipeDiscard()462     public void testDataPipeDiscard() {
463         Random random = new Random();
464         Core core = CoreImpl.getInstance();
465         Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
466         addHandlePairToClose(handles);
467 
468         // Writing a random 8 bytes message.
469         byte[] bytes = new byte[8];
470         random.nextBytes(bytes);
471         ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
472         buffer.put(bytes);
473         ResultAnd<Integer> result = handles.first.writeData(buffer, DataPipe.WriteFlags.NONE);
474         assertEquals(MojoResult.OK, result.getMojoResult());
475         assertEquals(bytes.length, result.getValue().intValue());
476 
477         // Discard bytes.
478         final int nbBytesToDiscard = 4;
479         assertEquals(nbBytesToDiscard,
480                 handles.second.discardData(nbBytesToDiscard, DataPipe.ReadFlags.NONE));
481 
482         // Read into a buffer.
483         ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length - nbBytesToDiscard);
484         ResultAnd<Integer> readResult =
485                 handles.second.readData(receiveBuffer, DataPipe.ReadFlags.NONE);
486         assertEquals(MojoResult.OK, readResult.getMojoResult());
487         assertEquals(bytes.length - nbBytesToDiscard, readResult.getValue().intValue());
488         assertEquals(0, receiveBuffer.position());
489         assertEquals(bytes.length - nbBytesToDiscard, receiveBuffer.limit());
490         byte[] receivedBytes = new byte[bytes.length - nbBytesToDiscard];
491         receiveBuffer.get(receivedBytes);
492         assertTrue(Arrays.equals(
493                 Arrays.copyOfRange(bytes, nbBytesToDiscard, bytes.length), receivedBytes));
494     }
495 
496     /**
497      * Testing {@link SharedBufferHandle}.
498      */
499     @SmallTest
testSharedBufferCreation()500     public void testSharedBufferCreation() {
501         Core core = CoreImpl.getInstance();
502         // Test creation with empty options.
503         core.createSharedBuffer(null, 8).close();
504         // Test creation with default options.
505         core.createSharedBuffer(new SharedBufferHandle.CreateOptions(), 8).close();
506     }
507 
508     /**
509      * Testing {@link SharedBufferHandle}.
510      */
511     @SmallTest
testSharedBufferDuplication()512     public void testSharedBufferDuplication() {
513         Core core = CoreImpl.getInstance();
514         SharedBufferHandle handle = core.createSharedBuffer(null, 8);
515         addHandleToClose(handle);
516 
517         // Test duplication with empty options.
518         handle.duplicate(null).close();
519         // Test creation with default options.
520         handle.duplicate(new SharedBufferHandle.DuplicateOptions()).close();
521     }
522 
523     /**
524      * Testing {@link SharedBufferHandle}.
525      */
526     @SmallTest
testSharedBufferSending()527     public void testSharedBufferSending() {
528         Core core = CoreImpl.getInstance();
529         SharedBufferHandle handle = core.createSharedBuffer(null, 8);
530         addHandleToClose(handle);
531         SharedBufferHandle newHandle = handle.duplicate(null);
532         addHandleToClose(newHandle);
533 
534         checkSharing(handle, newHandle);
535         checkSharing(newHandle, handle);
536     }
537 
538     /**
539      * Testing that invalid handle can be used with this implementation.
540      */
541     @SmallTest
testInvalidHandle()542     public void testInvalidHandle() {
543         Core core = CoreImpl.getInstance();
544         Handle handle = InvalidHandle.INSTANCE;
545 
546         // Checking wait.
547         boolean exception = false;
548         try {
549             core.wait(handle, Core.HandleSignals.WRITABLE, 0);
550         } catch (MojoException e) {
551             assertEquals(MojoResult.INVALID_ARGUMENT, e.getMojoResult());
552             exception = true;
553         }
554         assertTrue(exception);
555 
556         // Checking waitMany.
557         exception = false;
558         try {
559             List<Pair<Handle, Core.HandleSignals>> handles =
560                     new ArrayList<Pair<Handle, Core.HandleSignals>>();
561             handles.add(Pair.create(handle, Core.HandleSignals.WRITABLE));
562             core.waitMany(handles, 0);
563         } catch (MojoException e) {
564             assertEquals(MojoResult.INVALID_ARGUMENT, e.getMojoResult());
565             exception = true;
566         }
567         assertTrue(exception);
568 
569         // Checking sending an invalid handle.
570         // Until the behavior is changed on the C++ side, handle gracefully 2 different use case:
571         // - Receive a INVALID_ARGUMENT exception
572         // - Receive an invalid handle on the other side.
573         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
574         addHandlePairToClose(handles);
575         try {
576             handles.first.writeMessage(null, Collections.<Handle>singletonList(handle),
577                     MessagePipeHandle.WriteFlags.NONE);
578             ResultAnd<MessagePipeHandle.ReadMessageResult> readMessageResult =
579                     handles.second.readMessage(null, 1, MessagePipeHandle.ReadFlags.NONE);
580             assertEquals(1, readMessageResult.getValue().getHandlesCount());
581             assertFalse(readMessageResult.getValue().getHandles().get(0).isValid());
582         } catch (MojoException e) {
583             assertEquals(MojoResult.INVALID_ARGUMENT, e.getMojoResult());
584         }
585     }
586 
587     private static class AsyncWaiterResult implements Callback {
588         private int mResult = Integer.MIN_VALUE;
589         private MojoException mException = null;
590 
591         /**
592          * @see Callback#onResult(int)
593          */
594         @Override
onResult(int result)595         public void onResult(int result) {
596             this.mResult = result;
597         }
598 
599         /**
600          * @see Callback#onError(MojoException)
601          */
602         @Override
onError(MojoException exception)603         public void onError(MojoException exception) {
604             this.mException = exception;
605         }
606 
607         /**
608          * @return the result
609          */
getResult()610         public int getResult() {
611             return mResult;
612         }
613 
614         /**
615          * @return the exception
616          */
getException()617         public MojoException getException() {
618             return mException;
619         }
620     }
621 
622     /**
623      * Testing core {@link AsyncWaiter} implementation.
624      */
625     @SmallTest
testAsyncWaiterCorrectResult()626     public void testAsyncWaiterCorrectResult() {
627         Core core = CoreImpl.getInstance();
628 
629         // Checking a correct result.
630         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
631         addHandlePairToClose(handles);
632         final AsyncWaiterResult asyncWaiterResult = new AsyncWaiterResult();
633         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
634         assertEquals(null, asyncWaiterResult.getException());
635 
636         core.getDefaultAsyncWaiter().asyncWait(handles.first, Core.HandleSignals.READABLE,
637                 Core.DEADLINE_INFINITE, asyncWaiterResult);
638         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
639         assertEquals(null, asyncWaiterResult.getException());
640 
641         handles.second.writeMessage(
642                 ByteBuffer.allocateDirect(1), null, MessagePipeHandle.WriteFlags.NONE);
643         runLoopUntilIdle();
644         assertNull(asyncWaiterResult.getException());
645         assertEquals(MojoResult.OK, asyncWaiterResult.getResult());
646     }
647 
648     /**
649      * Testing core {@link AsyncWaiter} implementation.
650      */
651     @SmallTest
testAsyncWaiterClosingPeerHandle()652     public void testAsyncWaiterClosingPeerHandle() {
653         Core core = CoreImpl.getInstance();
654 
655         // Closing the peer handle.
656         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
657         addHandlePairToClose(handles);
658 
659         final AsyncWaiterResult asyncWaiterResult = new AsyncWaiterResult();
660         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
661         assertEquals(null, asyncWaiterResult.getException());
662 
663         core.getDefaultAsyncWaiter().asyncWait(handles.first, Core.HandleSignals.READABLE,
664                 Core.DEADLINE_INFINITE, asyncWaiterResult);
665         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
666         assertEquals(null, asyncWaiterResult.getException());
667 
668         runLoopUntilIdle();
669         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
670         assertEquals(null, asyncWaiterResult.getException());
671 
672         handles.second.close();
673         runLoopUntilIdle();
674         assertNull(asyncWaiterResult.getException());
675         assertEquals(MojoResult.FAILED_PRECONDITION, asyncWaiterResult.getResult());
676     }
677 
678     /**
679      * Testing core {@link AsyncWaiter} implementation.
680      */
681     @SmallTest
testAsyncWaiterClosingWaitingHandle()682     public void testAsyncWaiterClosingWaitingHandle() {
683         Core core = CoreImpl.getInstance();
684 
685         // Closing the peer handle.
686         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
687         addHandlePairToClose(handles);
688 
689         final AsyncWaiterResult asyncWaiterResult = new AsyncWaiterResult();
690         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
691         assertEquals(null, asyncWaiterResult.getException());
692 
693         core.getDefaultAsyncWaiter().asyncWait(handles.first, Core.HandleSignals.READABLE,
694                 Core.DEADLINE_INFINITE, asyncWaiterResult);
695         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
696         assertEquals(null, asyncWaiterResult.getException());
697 
698         runLoopUntilIdle();
699         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
700         assertEquals(null, asyncWaiterResult.getException());
701 
702         handles.first.close();
703         runLoopUntilIdle();
704         // TODO(qsr) Re-enable when MojoWaitMany handles it correctly.
705         // assertNull(asyncWaiterResult.getException());
706         // assertEquals(MojoResult.CANCELLED, asyncWaiterResult.getResult());
707     }
708 
709     /**
710      * Testing core {@link AsyncWaiter} implementation.
711      */
712     @SmallTest
testAsyncWaiterWaitingOnInvalidHandle()713     public void testAsyncWaiterWaitingOnInvalidHandle() {
714         Core core = CoreImpl.getInstance();
715 
716         // Closing the peer handle.
717         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
718         addHandlePairToClose(handles);
719 
720         final AsyncWaiterResult asyncWaiterResult = new AsyncWaiterResult();
721         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
722         assertEquals(null, asyncWaiterResult.getException());
723 
724         handles.first.close();
725         core.getDefaultAsyncWaiter().asyncWait(handles.first, Core.HandleSignals.READABLE,
726                 Core.DEADLINE_INFINITE, asyncWaiterResult);
727         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
728         assertEquals(null, asyncWaiterResult.getException());
729 
730         runLoopUntilIdle();
731         assertNotNull(asyncWaiterResult.getException());
732         assertEquals(MojoResult.INVALID_ARGUMENT,
733                 asyncWaiterResult.getException().getMojoResult());
734         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
735     }
736 
737     /**
738      * Testing core {@link AsyncWaiter} implementation.
739      */
740     @SmallTest
testAsyncWaiterWaitingOnDefaultInvalidHandle()741     public void testAsyncWaiterWaitingOnDefaultInvalidHandle() {
742         Core core = CoreImpl.getInstance();
743 
744         final AsyncWaiterResult asyncWaiterResult = new AsyncWaiterResult();
745         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
746         assertEquals(null, asyncWaiterResult.getException());
747 
748         core.getDefaultAsyncWaiter().asyncWait(InvalidHandle.INSTANCE, Core.HandleSignals.READABLE,
749                 Core.DEADLINE_INFINITE, asyncWaiterResult);
750         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
751         assertEquals(null, asyncWaiterResult.getException());
752 
753         runLoopUntilIdle();
754         assertNotNull(asyncWaiterResult.getException());
755         assertEquals(MojoResult.INVALID_ARGUMENT, asyncWaiterResult.getException().getMojoResult());
756         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
757     }
758 
759     /**
760      * Testing core {@link AsyncWaiter} implementation.
761      */
762     @SmallTest
testAsyncWaiterWaitingWithTimeout()763     public void testAsyncWaiterWaitingWithTimeout() {
764         Core core = CoreImpl.getInstance();
765 
766         // Closing the peer handle.
767         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
768         addHandlePairToClose(handles);
769 
770         final AsyncWaiterResult asyncWaiterResult = new AsyncWaiterResult();
771         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
772         assertEquals(null, asyncWaiterResult.getException());
773 
774         core.getDefaultAsyncWaiter().asyncWait(
775                 handles.first, Core.HandleSignals.READABLE, RUN_LOOP_TIMEOUT_MS, asyncWaiterResult);
776         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
777         assertEquals(null, asyncWaiterResult.getException());
778 
779         runLoopUntilIdle();
780         assertNull(asyncWaiterResult.getException());
781         assertEquals(MojoResult.DEADLINE_EXCEEDED, asyncWaiterResult.getResult());
782     }
783 
784     /**
785      * Testing core {@link AsyncWaiter} implementation.
786      */
787     @SmallTest
testAsyncWaiterCancelWaiting()788     public void testAsyncWaiterCancelWaiting() {
789         Core core = CoreImpl.getInstance();
790 
791         // Closing the peer handle.
792         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
793         addHandlePairToClose(handles);
794 
795         final AsyncWaiterResult asyncWaiterResult = new AsyncWaiterResult();
796         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
797         assertEquals(null, asyncWaiterResult.getException());
798 
799         Cancellable cancellable = core.getDefaultAsyncWaiter().asyncWait(handles.first,
800                 Core.HandleSignals.READABLE, Core.DEADLINE_INFINITE, asyncWaiterResult);
801         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
802         assertEquals(null, asyncWaiterResult.getException());
803 
804         runLoopUntilIdle();
805         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
806         assertEquals(null, asyncWaiterResult.getException());
807 
808         cancellable.cancel();
809         runLoopUntilIdle();
810         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
811         assertEquals(null, asyncWaiterResult.getException());
812 
813         handles.second.writeMessage(
814                 ByteBuffer.allocateDirect(1), null, MessagePipeHandle.WriteFlags.NONE);
815         runLoopUntilIdle();
816         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
817         assertEquals(null, asyncWaiterResult.getException());
818     }
819 
820     /**
821      * Testing core {@link AsyncWaiter} implementation.
822      */
823     @SmallTest
testAsyncWaiterImmediateCancelOnInvalidHandle()824     public void testAsyncWaiterImmediateCancelOnInvalidHandle() {
825         Core core = CoreImpl.getInstance();
826 
827         // Closing the peer handle.
828         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
829         addHandlePairToClose(handles);
830 
831         final AsyncWaiterResult asyncWaiterResult = new AsyncWaiterResult();
832         handles.first.close();
833         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
834         assertEquals(null, asyncWaiterResult.getException());
835 
836         Cancellable cancellable = core.getDefaultAsyncWaiter().asyncWait(handles.first,
837                 Core.HandleSignals.READABLE, Core.DEADLINE_INFINITE, asyncWaiterResult);
838         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
839         assertEquals(null, asyncWaiterResult.getException());
840         cancellable.cancel();
841 
842         runLoopUntilIdle();
843         assertEquals(Integer.MIN_VALUE, asyncWaiterResult.getResult());
844         assertEquals(null, asyncWaiterResult.getException());
845     }
846 
847     /**
848      * Testing the pass method on message pipes.
849      */
850     @SmallTest
testMessagePipeHandlePass()851     public void testMessagePipeHandlePass() {
852         Core core = CoreImpl.getInstance();
853         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
854         addHandlePairToClose(handles);
855 
856         assertTrue(handles.first.isValid());
857         MessagePipeHandle handleClone = handles.first.pass();
858 
859         addHandleToClose(handleClone);
860 
861         assertFalse(handles.first.isValid());
862         assertTrue(handleClone.isValid());
863         checkSendingMessage(handleClone, handles.second);
864         checkSendingMessage(handles.second, handleClone);
865     }
866 
867     /**
868      * Testing the pass method on data pipes.
869      */
870     @SmallTest
testDataPipeHandlePass()871     public void testDataPipeHandlePass() {
872         Core core = CoreImpl.getInstance();
873         Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
874         addHandlePairToClose(handles);
875 
876         DataPipe.ProducerHandle producerClone = handles.first.pass();
877         DataPipe.ConsumerHandle consumerClone = handles.second.pass();
878 
879         addHandleToClose(producerClone);
880         addHandleToClose(consumerClone);
881 
882         assertFalse(handles.first.isValid());
883         assertFalse(handles.second.isValid());
884         assertTrue(producerClone.isValid());
885         assertTrue(consumerClone.isValid());
886         checkSendingData(producerClone, consumerClone);
887     }
888 
889     /**
890      * Testing the pass method on shared buffers.
891      */
892     @SmallTest
testSharedBufferPass()893     public void testSharedBufferPass() {
894         Core core = CoreImpl.getInstance();
895         SharedBufferHandle handle = core.createSharedBuffer(null, 8);
896         addHandleToClose(handle);
897         SharedBufferHandle newHandle = handle.duplicate(null);
898         addHandleToClose(newHandle);
899 
900         SharedBufferHandle handleClone = handle.pass();
901         SharedBufferHandle newHandleClone = newHandle.pass();
902 
903         addHandleToClose(handleClone);
904         addHandleToClose(newHandleClone);
905 
906         assertFalse(handle.isValid());
907         assertTrue(handleClone.isValid());
908         checkSharing(handleClone, newHandleClone);
909         checkSharing(newHandleClone, handleClone);
910     }
911 
912     /**
913      * esting handle conversion to native and back.
914      */
915     @SmallTest
testHandleConversion()916     public void testHandleConversion() {
917         Core core = CoreImpl.getInstance();
918         Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
919         addHandlePairToClose(handles);
920 
921         MessagePipeHandle converted =
922                 core.acquireNativeHandle(handles.first.releaseNativeHandle()).toMessagePipeHandle();
923         addHandleToClose(converted);
924 
925         assertFalse(handles.first.isValid());
926 
927         checkSendingMessage(converted, handles.second);
928         checkSendingMessage(handles.second, converted);
929     }
930 }
931