| /* | |
| * Copyright (c) 2008, 2021, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* @test | |
| * @bug 4313887 6993267 | |
| * @summary Unit test for Sun-specific ExtendedCopyOption.INTERRUPTIBLE option | |
| * @modules jdk.unsupported | |
| * @library .. | |
| */ | |
| import java.io.IOException; | |
| import java.io.OutputStream; | |
| import java.nio.file.Files; | |
| import java.nio.file.FileStore; | |
| import java.nio.file.Path; | |
| import java.nio.file.StandardCopyOption; | |
| import java.util.concurrent.Callable; | |
| import java.util.concurrent.CountDownLatch; | |
| import java.util.concurrent.Executors; | |
| import java.util.concurrent.Future; | |
| import java.util.concurrent.ScheduledExecutorService; | |
| import com.sun.nio.file.ExtendedCopyOption; | |
| public class InterruptCopy { | |
| private static final long FILE_SIZE_TO_COPY = 1024L * 1024L * 1024L; | |
| private static final int INTERRUPT_DELAY_IN_MS = 50; | |
| private static final int CANCEL_DELAY_IN_MS = 10; | |
| public static void main(String[] args) throws Exception { | |
| Path dir = TestUtil.createTemporaryDirectory(); | |
| try { | |
| FileStore store = Files.getFileStore(dir); | |
| System.out.format("Checking space (%s)\n", store); | |
| long usableSpace = store.getUsableSpace(); | |
| if (usableSpace < 2*FILE_SIZE_TO_COPY) { | |
| System.out.println("Insufficient disk space to run test."); | |
| return; | |
| } | |
| doTest(dir); | |
| } finally { | |
| TestUtil.removeAll(dir); | |
| } | |
| } | |
| static void doTest(Path dir) throws Exception { | |
| final Path source = dir.resolve("foo"); | |
| final Path target = dir.resolve("bar"); | |
| // create source file (don't create it as sparse file because we | |
| // require the copy to take a long time) | |
| System.out.println("Creating source file..."); | |
| byte[] buf = new byte[32*1024]; | |
| long total = 0; | |
| try (OutputStream out = Files.newOutputStream(source)) { | |
| do { | |
| out.write(buf); | |
| total += buf.length; | |
| } while (total < FILE_SIZE_TO_COPY); | |
| } | |
| System.out.println("Source file created."); | |
| ScheduledExecutorService pool = | |
| Executors.newSingleThreadScheduledExecutor(); | |
| try { | |
| // copy source to target in main thread, interrupting it | |
| // after a delay | |
| final Thread me = Thread.currentThread(); | |
| final CountDownLatch interruptLatch = new CountDownLatch(1); | |
| Future<?> wakeup = pool.submit(new Runnable() { | |
| public void run() { | |
| try { | |
| interruptLatch.await(); | |
| Thread.sleep(INTERRUPT_DELAY_IN_MS); | |
| } catch (InterruptedException ignore) { | |
| } | |
| System.out.printf("Interrupting at %d ms...%n", | |
| System.currentTimeMillis()); | |
| me.interrupt(); | |
| } | |
| }); | |
| try { | |
| interruptLatch.countDown(); | |
| long theBeginning = System.currentTimeMillis(); | |
| System.out.printf("Copying file at %d ms...%n", theBeginning); | |
| Files.copy(source, target, ExtendedCopyOption.INTERRUPTIBLE); | |
| long theEnd = System.currentTimeMillis(); | |
| System.out.printf("Done copying at %d ms...%n", theEnd); | |
| long duration = theEnd - theBeginning; | |
| // If the copy was interrupted the target file should have been | |
| // deleted, so if the file does not exist, then the copy must | |
| // have been interrupted without throwing an exception; if the | |
| // file exists, then the copy finished before being interrupted | |
| // so not throwing an exception is not considered a failure | |
| if (Files.notExists(target)) | |
| throw new RuntimeException("Copy was not interrupted in " + | |
| duration + " ms"); | |
| } catch (IOException e) { | |
| boolean interrupted = Thread.interrupted(); | |
| if (!interrupted) | |
| throw new RuntimeException("Interrupt status was not set"); | |
| System.out.println("Copy failed (this is expected)."); | |
| } | |
| try { | |
| wakeup.get(); | |
| } catch (InterruptedException ignore) { } | |
| Thread.interrupted(); | |
| // copy source to target via task in thread pool, interrupting it | |
| // after a delay using cancel(true) | |
| CountDownLatch cancelLatch = new CountDownLatch(1); | |
| Future<Void> result = pool.submit(new Callable<Void>() { | |
| public Void call() throws IOException { | |
| cancelLatch.countDown(); | |
| System.out.printf("Copying file at %d ms...%n", | |
| System.currentTimeMillis()); | |
| Files.copy(source, target, ExtendedCopyOption.INTERRUPTIBLE, | |
| StandardCopyOption.REPLACE_EXISTING); | |
| System.out.printf("Done copying at %d ms...%n", | |
| System.currentTimeMillis()); | |
| return null; | |
| } | |
| }); | |
| try { | |
| cancelLatch.await(); | |
| Thread.sleep(CANCEL_DELAY_IN_MS); | |
| } catch (InterruptedException ignore) { | |
| } | |
| if (result.isDone()) | |
| throw new RuntimeException("Copy finished before cancellation"); | |
| System.out.printf("Cancelling at %d ms...%n", | |
| System.currentTimeMillis()); | |
| boolean cancelled = result.cancel(true); | |
| if (cancelled) | |
| System.out.println("Copy cancelled."); | |
| else { | |
| result.get(); | |
| throw new RuntimeException("Copy was not cancelled"); | |
| } | |
| } finally { | |
| pool.shutdown(); | |
| } | |
| } | |
| } |