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