gt:             result[i] = ch.write(buf[i], position[i]);
context: /*
   * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  /* @test
   * @bug 4607272 6822643 6830721 6842687
   * @summary Unit test for AsynchronousFileChannel
   */
  
  import java.nio.file.*;
  import java.nio.channels.*;
  import java.nio.ByteBuffer;
  import java.io.File;
  import java.io.IOException;
  import java.util.*;
  import java.util.concurrent.*;
  import java.util.concurrent.atomic.AtomicReference;
  import static java.nio.file.StandardOpenOption.*;
  
  public class Basic {
  
      private static final Random rand = new Random();
  
      public static void main(String[] args) throws IOException {
          // create temporary file
          File blah = File.createTempFile("blah", null);
          blah.deleteOnExit();
  
          final AsynchronousFileChannel ch = AsynchronousFileChannel
              .open(blah.toPath(), READ, WRITE);
  
          // run tests
          testUsingCompletionHandlers(ch);
          testUsingWaitOnResult(ch);
          testInterruptHandlerThread(ch);
  
          // close channel and invoke test that expects channel to be closed
          ch.close();
          testClosedChannel(ch);
  
          // these tests open the file themselves
          testLocking(blah.toPath());
          testCustomThreadPool(blah.toPath());
          testAsynchronousClose(blah.toPath());
          testCancel(blah.toPath());
          testTruncate(blah.toPath());
      }
  
      /*
       * Generate buffer with random contents
       * Writes buffer to file using a CompletionHandler to consume the result
       *    of each write operation
       * Reads file to EOF to a new buffer using a CompletionHandler to consume
       *    the result of each read operation
       * Compares buffer contents
       */
      static void testUsingCompletionHandlers(AsynchronousFileChannel ch)
          throws IOException
      {
          System.out.println("testUsingCompletionHandlers");
  
          ch.truncate(0L);
  
          // generate buffer with random elements and write it to file
          ByteBuffer src = genBuffer();
          writeFully(ch, src, 0L);
  
          // read to EOF or buffer is full
          ByteBuffer dst = (rand.nextBoolean()) ?
              ByteBuffer.allocateDirect(src.capacity()) :
              ByteBuffer.allocate(src.capacity());
          readAll(ch, dst, 0L);
  
          // check buffers are the same
          src.flip();
          dst.flip();
          if (!src.equals(dst)) {
              throw new RuntimeException("Contents differ");
          }
      }
  
      /*
       * Generate buffer with random contents
       * Writes buffer to file, invoking the Future's get method to wait for
       *    each write operation to complete
       * Reads file to EOF to a new buffer, invoking the Future's get method to
       *    wait for each write operation to complete
       * Compares buffer contents
       */
      static void testUsingWaitOnResult(AsynchronousFileChannel ch)
          throws IOException
      {
          System.out.println("testUsingWaitOnResult");
  
          ch.truncate(0L);
  
          // generate buffer
          ByteBuffer src = genBuffer();
  
          // write buffer completely to file
          long position = 0L;
          while (src.hasRemaining()) {
              Future<Integer> result = ch.write(src, position);
              try {
                  int n = result.get();
                  // update position
                  position += n;
              } catch (ExecutionException x) {
                  throw new RuntimeException(x.getCause());
              } catch (InterruptedException x) {
                  throw new RuntimeException(x);
              }
          }
  
          // read file into new buffer
          ByteBuffer dst = (rand.nextBoolean()) ?
              ByteBuffer.allocateDirect(src.capacity()) :
              ByteBuffer.allocate(src.capacity());
          position = 0L;
          int n;
          do {
              Future<Integer> result = ch.read(dst, position);
              try {
                  n = result.get();
  
                  // update position
                  if (n > 0) position += n;
              } catch (ExecutionException x) {
                  throw new RuntimeException(x.getCause());
              } catch (InterruptedException x) {
                  throw new RuntimeException(x);
              }
          } while (n > 0);
  
          // check buffers are the same
          src.flip();
          dst.flip();
          if (!src.equals(dst)) {
              throw new RuntimeException("Contents differ");
          }
      }
  
      // exercise lock methods
      static void testLocking(Path file) throws IOException {
          System.out.println("testLocking");
  
          AsynchronousFileChannel ch = AsynchronousFileChannel
              .open(file, READ, WRITE);
          FileLock fl;
          try {
              // test 1 - acquire lock and check that tryLock throws
              // OverlappingFileLockException
              try {
                  fl = ch.lock().get();
              } catch (ExecutionException x) {
                  throw new RuntimeException(x);
              } catch (InterruptedException x) {
                  throw new RuntimeException("Should not be interrupted");
              }
              if (!fl.acquiredBy().equals(ch))
                  throw new RuntimeException("FileLock#acquiredBy returned incorrect channel");
              try {
                  ch.tryLock();
                  throw new RuntimeException("OverlappingFileLockException expected");
              } catch (OverlappingFileLockException x) {
              }
              fl.release();
  
              // test 2 - acquire try and check that lock throws OverlappingFileLockException
              fl = ch.tryLock();
              if (fl == null)
                  throw new RuntimeException("Unable to acquire lock");
              try {
                  ch.lock((Void)null, new CompletionHandler<FileLock,Void> () {
                      public void completed(FileLock result, Void att) {
                      }
                      public void failed(Throwable exc, Void att) {
                      }
                  });
                  throw new RuntimeException("OverlappingFileLockException expected");
              } catch (OverlappingFileLockException x) {
              }
          } finally {
              ch.close();
          }
  
          // test 3 - channel is closed so FileLock should no longer be valid
          if (fl.isValid())
              throw new RuntimeException("FileLock expected to be invalid");
      }
  
      // interrupt should not close channel
      static void testInterruptHandlerThread(final AsynchronousFileChannel ch) {
          System.out.println("testInterruptHandlerThread");
  
          ByteBuffer buf = ByteBuffer.allocateDirect(100);
          final CountDownLatch latch = new CountDownLatch(1);
  
          ch.read(buf, 0L, (Void)null, new CompletionHandler<Integer,Void>() {
              public void completed(Integer result, Void att) {
                  try {
                      Thread.currentThread().interrupt();
                      long size = ch.size();
                      latch.countDown();
                  } catch (IOException x) {
                      x.printStackTrace();
                  }
              }
              public void failed(Throwable exc, Void att) {
              }
          });
  
          // wait for handler to complete
          await(latch);
      }
  
      // invoke method on closed channel
      static void testClosedChannel(AsynchronousFileChannel ch) {
          System.out.println("testClosedChannel");
  
          if (ch.isOpen())
              throw new RuntimeException("Channel should be closed");
  
          ByteBuffer buf = ByteBuffer.allocateDirect(100);
  
          // check read fails with ClosedChannelException
          try {
              ch.read(buf, 0L).get();
              throw new RuntimeException("ExecutionException expected");
          } catch (ExecutionException x) {
              if (!(x.getCause() instanceof ClosedChannelException))
                  throw new RuntimeException("Cause of ClosedChannelException expected");
          } catch (InterruptedException x) {
          }
  
          // check write fails with ClosedChannelException
          try {
              ch.write(buf, 0L).get();
              throw new RuntimeException("ExecutionException expected");
          } catch (ExecutionException x) {
              if (!(x.getCause() instanceof ClosedChannelException))
                  throw new RuntimeException("Cause of ClosedChannelException expected");
          } catch (InterruptedException x) {
          }
  
          // check lock fails with ClosedChannelException
          try {
              ch.lock().get();
              throw new RuntimeException("ExecutionException expected");
          } catch (ExecutionException x) {
              if (!(x.getCause() instanceof ClosedChannelException))
                  throw new RuntimeException("Cause of ClosedChannelException expected");
          } catch (InterruptedException x) {
          }
      }
  
  
      // exercise custom thread pool
      static void testCustomThreadPool(Path file) throws IOException {
          System.out.println("testCustomThreadPool");
  
          // records threads that are created
          final List<Thread> threads = new ArrayList<Thread>();
  
          ThreadFactory threadFactory = new ThreadFactory() {
               @Override
               public Thread newThread(Runnable r) {
                   Thread t = new Thread(r);
                   t.setDaemon(true);
                   synchronized (threads) {
                       threads.add(t);
                   }
                   return t;
               }
          };
  
          // exercise tests with varied number of threads
          for (int nThreads=1; nThreads<=5; nThreads++) {
              synchronized (threads) {
                  threads.clear();
              }
              ExecutorService executor = Executors.newFixedThreadPool(nThreads, threadFactory);
              Set<StandardOpenOption> opts = EnumSet.of(WRITE);
              AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, opts, executor);
              try {
                  for (int i=0; i<10; i++) {
                      // do I/O operation to see which thread invokes the completion handler
                      final AtomicReference<Thread> invoker = new AtomicReference<Thread>();
                      final CountDownLatch latch = new CountDownLatch(1);
  
                      ch.write(genBuffer(), 0L, (Void)null, new CompletionHandler<Integer,Void>() {
                          public void completed(Integer result, Void att) {
                              invoker.set(Thread.currentThread());
                              latch.countDown();
                          }
                          public void failed(Throwable exc, Void att) {
                          }
                      });
                      await(latch);
  
                      // check invoker
                      boolean found = false;
                      synchronized (threads) {
                          for (Thread t: threads) {
                              if (t == invoker.get()) {
                                  found = true;
                                  break;
                              }
                          }
                      }
                      if (!found)
                          throw new RuntimeException("Invoker thread not found");
                  }
              } finally {
                  ch.close();
                  executor.shutdown();
              }
          }
  
  
          // test sharing a thread pool between many channels
          ExecutorService executor = Executors
              .newFixedThreadPool(1+rand.nextInt(10), threadFactory);
          final int n = 50 + rand.nextInt(50);
          AsynchronousFileChannel[] channels = new AsynchronousFileChannel[n];
          try {
              for (int i=0; i<n; i++) {
                  Set<StandardOpenOption> opts = EnumSet.of(WRITE);
                  channels[i] = AsynchronousFileChannel.open(file, opts, executor);
                  final CountDownLatch latch = new CountDownLatch(1);
                  channels[i].write(genBuffer(), 0L, (Void)null, new CompletionHandler<Integer,Void>() {
                      public void completed(Integer result, Void att) {
                          latch.countDown();
                      }
                      public void failed(Throwable exc, Void att) {
                      }
                  });
                  await(latch);
  
                  // close ~half the channels
                  if (rand.nextBoolean())
                      channels[i].close();
              }
          } finally {
              // close remaining channels
              for (int i=0; i<n; i++) {
                  if (channels[i] != null) channels[i].close();
              }
              executor.shutdown();
          }
      }
  
      // exercise asynchronous close
      static void testAsynchronousClose(Path file) throws IOException {
          System.out.println("testAsynchronousClose");
  
          // create file
          AsynchronousFileChannel ch = AsynchronousFileChannel
              .open(file, WRITE, TRUNCATE_EXISTING);
          long size = 0L;
          do {
              ByteBuffer buf = genBuffer();
              int n = buf.remaining();
              writeFully(ch, buf, size);
              size += n;
          } while (size < (50L * 1024L * 1024L));
  
          ch.close();
  
          ch = AsynchronousFileChannel.open(file, WRITE, SYNC);
  
          // randomize number of writers, buffer size, and positions
  
          int nwriters = 1 + rand.nextInt(8);
          ByteBuffer[] buf = new ByteBuffer[nwriters];
          long[] position = new long[nwriters];
          for (int i=0; i<nwriters; i++) {
              buf[i] = genBuffer();
              position[i] = rand.nextInt((int)size);
          }
  
          // initiate I/O
          Future[] result = new Future[nwriters];
          for (int i=0; i<nwriters; i++) {
  