CoreImplTest.java revision 645501c2ab19a559ce82a1d5a29ced159a4c30fb
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
5package org.chromium.mojo.system.impl;
6
7import android.test.suitebuilder.annotation.SmallTest;
8
9import org.chromium.mojo.MojoTestCase;
10import org.chromium.mojo.system.AsyncWaiter;
11import org.chromium.mojo.system.AsyncWaiter.Callback;
12import org.chromium.mojo.system.AsyncWaiter.Cancellable;
13import org.chromium.mojo.system.Core;
14import org.chromium.mojo.system.Core.HandleSignals;
15import org.chromium.mojo.system.Core.HandleSignalsState;
16import org.chromium.mojo.system.Core.WaitManyResult;
17import org.chromium.mojo.system.Core.WaitResult;
18import org.chromium.mojo.system.DataPipe;
19import org.chromium.mojo.system.Handle;
20import org.chromium.mojo.system.InvalidHandle;
21import org.chromium.mojo.system.MessagePipeHandle;
22import org.chromium.mojo.system.MojoException;
23import org.chromium.mojo.system.MojoResult;
24import org.chromium.mojo.system.Pair;
25import org.chromium.mojo.system.ResultAnd;
26import org.chromium.mojo.system.SharedBufferHandle;
27
28import java.nio.ByteBuffer;
29import java.util.ArrayList;
30import java.util.Arrays;
31import java.util.Collections;
32import java.util.List;
33import java.util.Random;
34import java.util.concurrent.Executors;
35import java.util.concurrent.ScheduledExecutorService;
36import java.util.concurrent.TimeUnit;
37
38/**
39 * Testing the core API.
40 */
41public 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
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
73    private void addHandleToClose(Handle handle) {
74        mHandlesToClose.add(handle);
75    }
76
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
88        CloseHandle(Handle handle) {
89            mHandle = handle;
90        }
91
92        @Override
93        public void run() {
94            mHandle.close();
95        }
96    }
97
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
595        public void onResult(int result) {
596            this.mResult = result;
597        }
598
599        /**
600         * @see Callback#onError(MojoException)
601         */
602        @Override
603        public void onError(MojoException exception) {
604            this.mException = exception;
605        }
606
607        /**
608         * @return the result
609         */
610        public int getResult() {
611            return mResult;
612        }
613
614        /**
615         * @return the exception
616         */
617        public MojoException getException() {
618            return mException;
619        }
620    }
621
622    /**
623     * Testing core {@link AsyncWaiter} implementation.
624     */
625    @SmallTest
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
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
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
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
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
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
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
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
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
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
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
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