jdk/test/java/nio/file/Path/CopyAndMove.java
changeset 2057 3acf8e5e2ca0
child 3065 452aaa2899fc
equal deleted inserted replaced
2056:115e09b7a004 2057:3acf8e5e2ca0
       
     1 /*
       
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    24 /* @test
       
    25  * @bug 4313887
       
    26  * @summary Unit test for java.nio.file.Path copyTo/moveTo methods
       
    27  * @library ..
       
    28  */
       
    29 
       
    30 import java.nio.ByteBuffer;
       
    31 import java.nio.file.*;
       
    32 import static java.nio.file.StandardCopyOption.*;
       
    33 import static java.nio.file.LinkOption.*;
       
    34 import java.nio.file.attribute.*;
       
    35 import java.io.*;
       
    36 import java.util.*;
       
    37 
       
    38 public class CopyAndMove {
       
    39     static final Random rand = new Random();
       
    40     static boolean heads() { return rand.nextBoolean(); }
       
    41     static boolean supportsLinks;
       
    42 
       
    43     public static void main(String[] args) throws Exception {
       
    44         Path dir1 = TestUtil.createTemporaryDirectory();
       
    45         try {
       
    46             supportsLinks = TestUtil.supportsLinks(dir1);
       
    47 
       
    48             // Exercise copyTo
       
    49             doCopyTests(dir1);
       
    50 
       
    51             // Exercise moveTo
       
    52             // if test.dir differs to temporary file system then can test
       
    53             // moving between devices
       
    54             String testDir = System.getProperty("test.dir");
       
    55             Path dir2 = (testDir != null) ? Paths.get(testDir) : dir1;
       
    56             doMoveTests(dir1, dir2);
       
    57 
       
    58         } finally {
       
    59             TestUtil.removeAll(dir1);
       
    60         }
       
    61     }
       
    62 
       
    63     static void checkBasicAttributes(BasicFileAttributes attrs1,
       
    64                                      BasicFileAttributes attrs2)
       
    65     {
       
    66         // check file type
       
    67         assertTrue(attrs1.isRegularFile() == attrs2.isRegularFile());
       
    68         assertTrue(attrs1.isDirectory() == attrs2.isDirectory());
       
    69         assertTrue(attrs1.isSymbolicLink() == attrs2.isSymbolicLink());
       
    70         assertTrue(attrs1.isOther() == attrs2.isOther());
       
    71 
       
    72         // check last modified time (assume millisecond precision)
       
    73         long time1 = attrs1.resolution().toMillis(attrs1.lastModifiedTime());
       
    74         long time2 = attrs1.resolution().toMillis(attrs2.lastModifiedTime());
       
    75         assertTrue(time1 == time2);
       
    76 
       
    77         // check size
       
    78         if (attrs1.isRegularFile())
       
    79             assertTrue(attrs1.size() == attrs2.size());
       
    80     }
       
    81 
       
    82     static void checkPosixAttributes(PosixFileAttributes attrs1,
       
    83                                      PosixFileAttributes attrs2)
       
    84     {
       
    85         assertTrue(attrs1.permissions().equals(attrs2.permissions()));
       
    86         assertTrue(attrs1.owner().equals(attrs2.owner()));
       
    87         assertTrue(attrs1.group().equals(attrs2.group()));
       
    88     }
       
    89 
       
    90     static void checkDosAttributes(DosFileAttributes attrs1,
       
    91                                    DosFileAttributes attrs2)
       
    92     {
       
    93         assertTrue(attrs1.isReadOnly() == attrs2.isReadOnly());
       
    94         assertTrue(attrs1.isHidden() == attrs2.isHidden());
       
    95         assertTrue(attrs1.isArchive() == attrs2.isArchive());
       
    96         assertTrue(attrs1.isSystem() == attrs2.isSystem());
       
    97     }
       
    98 
       
    99     static void checkUserDefinedFileAttributes(Map<String,ByteBuffer> attrs1,
       
   100                                      Map<String,ByteBuffer> attrs2)
       
   101     {
       
   102         assert attrs1.size() == attrs2.size();
       
   103         for (String name: attrs1.keySet()) {
       
   104             ByteBuffer bb1 = attrs1.get(name);
       
   105             ByteBuffer bb2 = attrs2.get(name);
       
   106             assertTrue(bb2 != null);
       
   107             assertTrue(bb1.equals(bb2));
       
   108         }
       
   109     }
       
   110 
       
   111     static Map<String,ByteBuffer> readUserDefinedFileAttributes(Path file)
       
   112         throws IOException
       
   113     {
       
   114         UserDefinedFileAttributeView view = file
       
   115             .getFileAttributeView(UserDefinedFileAttributeView.class);
       
   116         Map<String,ByteBuffer> result = new HashMap<String,ByteBuffer>();
       
   117         for (String name: view.list()) {
       
   118             int size = view.size(name);
       
   119             ByteBuffer bb = ByteBuffer.allocate(size);
       
   120             int n = view.read(name, bb);
       
   121             assertTrue(n == size);
       
   122             bb.flip();
       
   123             result.put(name, bb);
       
   124         }
       
   125         return result;
       
   126     }
       
   127 
       
   128     // move source to target with verification
       
   129     static void moveAndVerify(Path source, Path target, CopyOption... options)
       
   130         throws IOException
       
   131     {
       
   132         // read attributes before file is moved
       
   133         BasicFileAttributes basicAttributes = null;
       
   134         PosixFileAttributes posixAttributes = null;
       
   135         DosFileAttributes dosAttributes = null;
       
   136         Map<String,ByteBuffer> namedAttributes = null;
       
   137 
       
   138         // get file attributes of source file
       
   139         String os = System.getProperty("os.name");
       
   140         if (os.equals("SunOS") || os.equals("Linux")) {
       
   141             posixAttributes = Attributes.readPosixFileAttributes(source, NOFOLLOW_LINKS);
       
   142             basicAttributes = posixAttributes;
       
   143         }
       
   144         if (os.startsWith("Windows")) {
       
   145             dosAttributes = Attributes.readDosFileAttributes(source, NOFOLLOW_LINKS);
       
   146             basicAttributes = dosAttributes;
       
   147         }
       
   148         if (basicAttributes == null)
       
   149             basicAttributes = Attributes.readBasicFileAttributes(source, NOFOLLOW_LINKS);
       
   150 
       
   151         // hash file contents if regular file
       
   152         int hash = (basicAttributes.isRegularFile()) ? computeHash(source) : 0;
       
   153 
       
   154         // record link target if symbolic link
       
   155         Path linkTarget = null;
       
   156         if (basicAttributes.isSymbolicLink())
       
   157             linkTarget = source.readSymbolicLink();
       
   158 
       
   159         // read named attributes if available (and file is not a sym link)
       
   160         if (!basicAttributes.isSymbolicLink() &&
       
   161             source.getFileStore().supportsFileAttributeView("xattr"))
       
   162         {
       
   163             namedAttributes = readUserDefinedFileAttributes(source);
       
   164         }
       
   165 
       
   166         // move file
       
   167         source.moveTo(target, options);
       
   168 
       
   169         // verify source does not exist
       
   170         assertTrue(source.notExists());
       
   171 
       
   172         // verify file contents
       
   173         if (basicAttributes.isRegularFile()) {
       
   174             if (computeHash(target) != hash)
       
   175                 throw new RuntimeException("Failed to verify move of regular file");
       
   176         }
       
   177 
       
   178         // verify link target
       
   179         if (basicAttributes.isSymbolicLink()) {
       
   180             if (!target.readSymbolicLink().equals(linkTarget))
       
   181                 throw new RuntimeException("Failed to verify move of symbolic link");
       
   182         }
       
   183 
       
   184         // verify basic attributes
       
   185         checkBasicAttributes(basicAttributes,
       
   186             Attributes.readBasicFileAttributes(target, NOFOLLOW_LINKS));
       
   187 
       
   188         // verify POSIX attributes
       
   189         if (posixAttributes != null && !basicAttributes.isSymbolicLink()) {
       
   190             checkPosixAttributes(posixAttributes,
       
   191                 Attributes.readPosixFileAttributes(target, NOFOLLOW_LINKS));
       
   192         }
       
   193 
       
   194         // verify DOS attributes
       
   195         if (dosAttributes != null && !basicAttributes.isSymbolicLink()) {
       
   196             checkDosAttributes(dosAttributes,
       
   197                 Attributes.readDosFileAttributes(target, NOFOLLOW_LINKS));
       
   198         }
       
   199 
       
   200         // verify named attributes
       
   201         if (namedAttributes != null &&
       
   202             target.getFileStore().supportsFileAttributeView("xattr"))
       
   203         {
       
   204             checkUserDefinedFileAttributes(namedAttributes, readUserDefinedFileAttributes(target));
       
   205         }
       
   206     }
       
   207 
       
   208     /**
       
   209      * Tests all possible ways to invoke moveTo
       
   210      */
       
   211     static void doMoveTests(Path dir1, Path dir2) throws IOException {
       
   212         Path source, target, entry;
       
   213 
       
   214         boolean sameDevice = dir1.getFileStore().equals(dir2.getFileStore());
       
   215 
       
   216         // -- regular file --
       
   217 
       
   218         /**
       
   219          * Test: move regular file, target does not exist
       
   220          */
       
   221         source = createSourceFile(dir1);
       
   222         target = getTargetFile(dir1);
       
   223         moveAndVerify(source, target);
       
   224         target.delete();
       
   225 
       
   226         /**
       
   227          * Test: move regular file, target exists
       
   228          */
       
   229         source = createSourceFile(dir1);
       
   230         target = getTargetFile(dir1).createFile();
       
   231         try {
       
   232             moveAndVerify(source, target);
       
   233             throw new RuntimeException("FileAlreadyExistsException expected");
       
   234         } catch (FileAlreadyExistsException x) {
       
   235         }
       
   236         target.delete();
       
   237         target.createDirectory();
       
   238         try {
       
   239             moveAndVerify(source, target);
       
   240             throw new RuntimeException("FileAlreadyExistsException expected");
       
   241         } catch (FileAlreadyExistsException x) {
       
   242         }
       
   243         source.delete();
       
   244         target.delete();
       
   245 
       
   246         /**
       
   247          * Test: move regular file, target does not exist
       
   248          */
       
   249         source = createSourceFile(dir1);
       
   250         target = getTargetFile(dir1);
       
   251         moveAndVerify(source, target, REPLACE_EXISTING);
       
   252         target.delete();
       
   253 
       
   254         /**
       
   255          * Test: move regular file, target exists
       
   256          */
       
   257         source = createSourceFile(dir1);
       
   258         target = getTargetFile(dir1).createFile();
       
   259         moveAndVerify(source, target, REPLACE_EXISTING);
       
   260         target.delete();
       
   261 
       
   262         /**
       
   263          * Test: move regular file, target exists and is empty directory
       
   264          */
       
   265         source = createSourceFile(dir1);
       
   266         target = getTargetFile(dir1).createDirectory();
       
   267         moveAndVerify(source, target, REPLACE_EXISTING);
       
   268         target.delete();
       
   269 
       
   270         /**
       
   271          * Test: move regular file, target exists and is non-empty directory
       
   272          */
       
   273         source = createSourceFile(dir1);
       
   274         target = getTargetFile(dir1).createDirectory();
       
   275         entry = target.resolve("foo").createFile();
       
   276         try {
       
   277             moveAndVerify(source, target);
       
   278             throw new RuntimeException("FileAlreadyExistsException expected");
       
   279         } catch (FileAlreadyExistsException x) {
       
   280         }
       
   281         entry.delete();
       
   282         source.delete();
       
   283         target.delete();
       
   284 
       
   285         /**
       
   286          * Test atomic move of regular file (same file store)
       
   287          */
       
   288         source = createSourceFile(dir1);
       
   289         target = getTargetFile(dir1);
       
   290         moveAndVerify(source, target, ATOMIC_MOVE);
       
   291         target.delete();
       
   292 
       
   293         /**
       
   294          * Test atomic move of regular file (different file store)
       
   295          */
       
   296         if (!sameDevice) {
       
   297             source = createSourceFile(dir1);
       
   298             target = getTargetFile(dir2);
       
   299             try {
       
   300                 moveAndVerify(source, target, ATOMIC_MOVE);
       
   301                 throw new RuntimeException("AtomicMoveNotSupportedException expected");
       
   302             } catch (AtomicMoveNotSupportedException x) {
       
   303             }
       
   304             source.delete();
       
   305         }
       
   306 
       
   307         // -- directories --
       
   308 
       
   309         /*
       
   310          * Test: move empty directory, target does not exist
       
   311          */
       
   312         source = createSourceDirectory(dir1);
       
   313         target = getTargetFile(dir1);
       
   314         moveAndVerify(source, target);
       
   315         target.delete();
       
   316 
       
   317         /**
       
   318          * Test: move empty directory, target exists
       
   319          */
       
   320         source = createSourceDirectory(dir1);
       
   321         target = getTargetFile(dir1).createFile();
       
   322         try {
       
   323             moveAndVerify(source, target);
       
   324             throw new RuntimeException("FileAlreadyExistsException expected");
       
   325         } catch (FileAlreadyExistsException x) {
       
   326         }
       
   327         target.delete();
       
   328         target.createDirectory();
       
   329         try {
       
   330             moveAndVerify(source, target);
       
   331             throw new RuntimeException("FileAlreadyExistsException expected");
       
   332         } catch (FileAlreadyExistsException x) {
       
   333         }
       
   334         source.delete();
       
   335         target.delete();
       
   336 
       
   337         /**
       
   338          * Test: move empty directory, target does not exist
       
   339          */
       
   340         source = createSourceDirectory(dir1);
       
   341         target = getTargetFile(dir1);
       
   342         moveAndVerify(source, target, REPLACE_EXISTING);
       
   343         target.delete();
       
   344 
       
   345         /**
       
   346          * Test: move empty directory, target exists
       
   347          */
       
   348         source = createSourceDirectory(dir1);
       
   349         target = getTargetFile(dir1).createFile();
       
   350         moveAndVerify(source, target, REPLACE_EXISTING);
       
   351         target.delete();
       
   352 
       
   353         /**
       
   354          * Test: move empty, target exists and is empty directory
       
   355          */
       
   356         source = createSourceDirectory(dir1);
       
   357         target = getTargetFile(dir1).createDirectory();
       
   358         moveAndVerify(source, target, REPLACE_EXISTING);
       
   359         target.delete();
       
   360 
       
   361         /**
       
   362          * Test: move empty directory, target exists and is non-empty directory
       
   363          */
       
   364         source = createSourceDirectory(dir1);
       
   365         target = getTargetFile(dir1).createDirectory();
       
   366         entry = target.resolve("foo").createFile();
       
   367         try {
       
   368             moveAndVerify(source, target, REPLACE_EXISTING);
       
   369             throw new RuntimeException("FileAlreadyExistsException expected");
       
   370         } catch (FileAlreadyExistsException x) {
       
   371         }
       
   372         entry.delete();
       
   373         source.delete();
       
   374         target.delete();
       
   375 
       
   376         /**
       
   377          * Test: move non-empty directory (same file system)
       
   378          */
       
   379         source = createSourceDirectory(dir1);
       
   380         source.resolve("foo").createFile();
       
   381         target = getTargetFile(dir1);
       
   382         moveAndVerify(source, target);
       
   383         target.resolve("foo").delete();
       
   384         target.delete();
       
   385 
       
   386         /**
       
   387          * Test: move non-empty directory (different file store)
       
   388          */
       
   389         if (!sameDevice) {
       
   390             source = createSourceDirectory(dir1);
       
   391             source.resolve("foo").createFile();
       
   392             target = getTargetFile(dir2);
       
   393             try {
       
   394                 moveAndVerify(source, target);
       
   395                 throw new RuntimeException("IOException expected");
       
   396             } catch (IOException x) {
       
   397             }
       
   398             source.resolve("foo").delete();
       
   399             source.delete();
       
   400         }
       
   401 
       
   402         /**
       
   403          * Test atomic move of directory (same file store)
       
   404          */
       
   405         source = createSourceDirectory(dir1);
       
   406         source.resolve("foo").createFile();
       
   407         target = getTargetFile(dir1);
       
   408         moveAndVerify(source, target, ATOMIC_MOVE);
       
   409         target.resolve("foo").delete();
       
   410         target.delete();
       
   411 
       
   412         // -- symbolic links --
       
   413 
       
   414         /**
       
   415          * Test: Move symbolic link to file, target does not exist
       
   416          */
       
   417         if (supportsLinks) {
       
   418             Path tmp = createSourceFile(dir1);
       
   419             source = dir1.resolve("link").createSymbolicLink(tmp);
       
   420             target = getTargetFile(dir1);
       
   421             moveAndVerify(source, target);
       
   422             target.delete();
       
   423             tmp.delete();
       
   424         }
       
   425 
       
   426         /**
       
   427          * Test: Move symbolic link to directory, target does not exist
       
   428          */
       
   429         if (supportsLinks) {
       
   430             source = dir1.resolve("link").createSymbolicLink(dir2);
       
   431             target = getTargetFile(dir1);
       
   432             moveAndVerify(source, target);
       
   433             target.delete();
       
   434         }
       
   435 
       
   436         /**
       
   437          * Test: Move broken symbolic link, target does not exists
       
   438          */
       
   439         if (supportsLinks) {
       
   440             Path tmp = Paths.get("doesnotexist");
       
   441             source = dir1.resolve("link").createSymbolicLink(tmp);
       
   442             target = getTargetFile(dir1);
       
   443             moveAndVerify(source, target);
       
   444             target.delete();
       
   445         }
       
   446 
       
   447         /**
       
   448          * Test: Move symbolic link, target exists
       
   449          */
       
   450         if (supportsLinks) {
       
   451             source = dir1.resolve("link").createSymbolicLink(dir2);
       
   452             target = getTargetFile(dir1).createFile();
       
   453             try {
       
   454                 moveAndVerify(source, target);
       
   455                 throw new RuntimeException("FileAlreadyExistsException expected");
       
   456             } catch (FileAlreadyExistsException x) {
       
   457             }
       
   458             source.delete();
       
   459             target.delete();
       
   460         }
       
   461 
       
   462         /**
       
   463          * Test: Move regular file, target exists
       
   464          */
       
   465         if (supportsLinks) {
       
   466             source = dir1.resolve("link").createSymbolicLink(dir2);
       
   467             target = getTargetFile(dir1).createFile();
       
   468             moveAndVerify(source, target, REPLACE_EXISTING);
       
   469             target.delete();
       
   470         }
       
   471 
       
   472         /**
       
   473          * Test: move symbolic link, target exists and is empty directory
       
   474          */
       
   475         if (supportsLinks) {
       
   476             source = dir1.resolve("link").createSymbolicLink(dir2);
       
   477             target = getTargetFile(dir1).createDirectory();
       
   478             moveAndVerify(source, target, REPLACE_EXISTING);
       
   479             target.delete();
       
   480         }
       
   481 
       
   482         /**
       
   483          * Test: symbolic link, target exists and is non-empty directory
       
   484          */
       
   485         if (supportsLinks) {
       
   486             source = dir1.resolve("link").createSymbolicLink(dir2);
       
   487             target = getTargetFile(dir1).createDirectory();
       
   488             entry = target.resolve("foo").createFile();
       
   489             try {
       
   490                 moveAndVerify(source, target);
       
   491                 throw new RuntimeException("FileAlreadyExistsException expected");
       
   492             } catch (FileAlreadyExistsException x) {
       
   493             }
       
   494             entry.delete();
       
   495             source.delete();
       
   496             target.delete();
       
   497         }
       
   498 
       
   499         /**
       
   500          * Test atomic move of symbolic link (same file store)
       
   501          */
       
   502         if (supportsLinks) {
       
   503             source = dir1.resolve("link").createSymbolicLink(dir1);
       
   504             target = getTargetFile(dir1).createFile();
       
   505             moveAndVerify(source, target, REPLACE_EXISTING);
       
   506             target.delete();
       
   507         }
       
   508 
       
   509         // -- misc. tests --
       
   510 
       
   511         /**
       
   512          * Test nulls
       
   513          */
       
   514         source = createSourceFile(dir1);
       
   515         target = getTargetFile(dir1);
       
   516         try {
       
   517             source.moveTo(null);
       
   518             throw new RuntimeException("NullPointerException expected");
       
   519         } catch (NullPointerException x) { }
       
   520         try {
       
   521             source.moveTo(target, (CopyOption[])null);
       
   522             throw new RuntimeException("NullPointerException expected");
       
   523         } catch (NullPointerException x) { }
       
   524         try {
       
   525             CopyOption[] opts = { REPLACE_EXISTING, null };
       
   526             source.moveTo(target, opts);
       
   527             throw new RuntimeException("NullPointerException expected");
       
   528         } catch (NullPointerException x) { }
       
   529         source.delete();
       
   530 
       
   531         /**
       
   532          * Test UOE
       
   533          */
       
   534         source = createSourceFile(dir1);
       
   535         target = getTargetFile(dir1);
       
   536         try {
       
   537             source.moveTo(target, new CopyOption() { });
       
   538         } catch (UnsupportedOperationException x) { }
       
   539         try {
       
   540             source.moveTo(target, REPLACE_EXISTING,  new CopyOption() { });
       
   541         } catch (UnsupportedOperationException x) { }
       
   542         source.delete();
       
   543     }
       
   544 
       
   545     // copy source to target with verification
       
   546     static void copyAndVerify(Path source, Path target, CopyOption... options)
       
   547         throws IOException
       
   548     {
       
   549         source.copyTo(target, options);
       
   550 
       
   551         // get attributes of source and target file to verify copy
       
   552         boolean followLinks = true;
       
   553         LinkOption[] linkOptions = new LinkOption[0];
       
   554         boolean copyAttributes = false;
       
   555         for (CopyOption opt : options) {
       
   556             if (opt == NOFOLLOW_LINKS) {
       
   557                 followLinks = false;
       
   558                 linkOptions = new LinkOption[] { NOFOLLOW_LINKS };
       
   559             }
       
   560             if (opt == COPY_ATTRIBUTES)
       
   561                 copyAttributes = true;
       
   562         }
       
   563         BasicFileAttributes basicAttributes = Attributes
       
   564             .readBasicFileAttributes(source, linkOptions);
       
   565 
       
   566         // check hash if regular file
       
   567         if (basicAttributes.isRegularFile())
       
   568             assertTrue(computeHash(source) == computeHash(target));
       
   569 
       
   570         // check link target if symbolic link
       
   571         if (basicAttributes.isSymbolicLink())
       
   572             assert( source.readSymbolicLink().equals(target.readSymbolicLink()));
       
   573 
       
   574         // check that attributes are copied
       
   575         if (copyAttributes && followLinks) {
       
   576             checkBasicAttributes(basicAttributes,
       
   577                 Attributes.readBasicFileAttributes(source, linkOptions));
       
   578 
       
   579             // check POSIX attributes are copied
       
   580             String os = System.getProperty("os.name");
       
   581             if (os.equals("SunOS") || os.equals("Linux")) {
       
   582                 checkPosixAttributes(
       
   583                     Attributes.readPosixFileAttributes(source, linkOptions),
       
   584                     Attributes.readPosixFileAttributes(target, linkOptions));
       
   585             }
       
   586 
       
   587             // check DOS attributes are copied
       
   588             if (os.startsWith("Windows")) {
       
   589                 checkDosAttributes(
       
   590                     Attributes.readDosFileAttributes(source, linkOptions),
       
   591                     Attributes.readDosFileAttributes(target, linkOptions));
       
   592             }
       
   593 
       
   594             // check named attributes are copied
       
   595             if (followLinks &&
       
   596                 source.getFileStore().supportsFileAttributeView("xattr") &&
       
   597                 target.getFileStore().supportsFileAttributeView("xattr"))
       
   598             {
       
   599                 checkUserDefinedFileAttributes(readUserDefinedFileAttributes(source),
       
   600                                      readUserDefinedFileAttributes(target));
       
   601             }
       
   602         }
       
   603     }
       
   604 
       
   605     /**
       
   606      * Tests all possible ways to invoke copyTo
       
   607      */
       
   608     static void doCopyTests(Path dir) throws IOException {
       
   609         Path source, target, link, entry;
       
   610 
       
   611         // -- regular file --
       
   612 
       
   613         /**
       
   614          * Test: move regular file, target does not exist
       
   615          */
       
   616         source = createSourceFile(dir);
       
   617         target = getTargetFile(dir);
       
   618         copyAndVerify(source, target);
       
   619         source.delete();
       
   620         target.delete();
       
   621 
       
   622         /**
       
   623          * Test: copy regular file, target exists
       
   624          */
       
   625         source = createSourceFile(dir);
       
   626         target = getTargetFile(dir).createFile();
       
   627         try {
       
   628             copyAndVerify(source, target);
       
   629             throw new RuntimeException("FileAlreadyExistsException expected");
       
   630         } catch (FileAlreadyExistsException x) {
       
   631         }
       
   632         target.delete();
       
   633         target.createDirectory();
       
   634         try {
       
   635             copyAndVerify(source, target);
       
   636             throw new RuntimeException("FileAlreadyExistsException expected");
       
   637         } catch (FileAlreadyExistsException x) {
       
   638         }
       
   639         source.delete();
       
   640         target.delete();
       
   641 
       
   642         /**
       
   643          * Test: copy regular file, target does not exist
       
   644          */
       
   645         source = createSourceFile(dir);
       
   646         target = getTargetFile(dir);
       
   647         copyAndVerify(source, target, REPLACE_EXISTING);
       
   648         source.delete();
       
   649         target.delete();
       
   650 
       
   651         /**
       
   652          * Test: copy regular file, target exists
       
   653          */
       
   654         source = createSourceFile(dir);
       
   655         target = getTargetFile(dir).createFile();
       
   656         copyAndVerify(source, target, REPLACE_EXISTING);
       
   657         source.delete();
       
   658         target.delete();
       
   659 
       
   660         /**
       
   661          * Test: copy regular file, target exists and is empty directory
       
   662          */
       
   663         source = createSourceFile(dir);
       
   664         target = getTargetFile(dir).createDirectory();
       
   665         copyAndVerify(source, target, REPLACE_EXISTING);
       
   666         source.delete();
       
   667         target.delete();
       
   668 
       
   669         /**
       
   670          * Test: copy regular file, target exists and is non-empty directory
       
   671          */
       
   672         source = createSourceFile(dir);
       
   673         target = getTargetFile(dir).createDirectory();
       
   674         entry = target.resolve("foo").createFile();
       
   675         try {
       
   676             copyAndVerify(source, target);
       
   677             throw new RuntimeException("FileAlreadyExistsException expected");
       
   678         } catch (FileAlreadyExistsException x) {
       
   679         }
       
   680         entry.delete();
       
   681         source.delete();
       
   682         target.delete();
       
   683 
       
   684         /**
       
   685          * Test: copy regular file + attributes
       
   686          */
       
   687         source = createSourceFile(dir);
       
   688         target = getTargetFile(dir);
       
   689         copyAndVerify(source, target, COPY_ATTRIBUTES);
       
   690         source.delete();
       
   691         target.delete();
       
   692 
       
   693 
       
   694         // -- directory --
       
   695 
       
   696         /*
       
   697          * Test: copy directory, target does not exist
       
   698          */
       
   699         source = createSourceDirectory(dir);
       
   700         target = getTargetFile(dir);
       
   701         copyAndVerify(source, target);
       
   702         source.delete();
       
   703         target.delete();
       
   704 
       
   705         /**
       
   706          * Test: copy directory, target exists
       
   707          */
       
   708         source = createSourceDirectory(dir);
       
   709         target = getTargetFile(dir).createFile();
       
   710         try {
       
   711             copyAndVerify(source, target);
       
   712             throw new RuntimeException("FileAlreadyExistsException expected");
       
   713         } catch (FileAlreadyExistsException x) {
       
   714         }
       
   715         target.delete();
       
   716         target.createDirectory();
       
   717         try {
       
   718             copyAndVerify(source, target);
       
   719             throw new RuntimeException("FileAlreadyExistsException expected");
       
   720         } catch (FileAlreadyExistsException x) {
       
   721         }
       
   722         source.delete();
       
   723         target.delete();
       
   724 
       
   725         /**
       
   726          * Test: copy directory, target does not exist
       
   727          */
       
   728         source = createSourceDirectory(dir);
       
   729         target = getTargetFile(dir);
       
   730         copyAndVerify(source, target, REPLACE_EXISTING);
       
   731         source.delete();
       
   732         target.delete();
       
   733 
       
   734         /**
       
   735          * Test: copy directory, target exists
       
   736          */
       
   737         source = createSourceDirectory(dir);
       
   738         target = getTargetFile(dir).createFile();
       
   739         copyAndVerify(source, target, REPLACE_EXISTING);
       
   740         source.delete();
       
   741         target.delete();
       
   742 
       
   743         /**
       
   744          * Test: copy directory, target exists and is empty directory
       
   745          */
       
   746         source = createSourceDirectory(dir);
       
   747         target = getTargetFile(dir).createDirectory();
       
   748         copyAndVerify(source, target, REPLACE_EXISTING);
       
   749         source.delete();
       
   750         target.delete();
       
   751 
       
   752         /**
       
   753          * Test: copy directory, target exists and is non-empty directory
       
   754          */
       
   755         source = createSourceDirectory(dir);
       
   756         target = getTargetFile(dir).createDirectory();
       
   757         entry = target.resolve("foo").createFile();
       
   758         try {
       
   759             copyAndVerify(source, target, REPLACE_EXISTING);
       
   760             throw new RuntimeException("FileAlreadyExistsException expected");
       
   761         } catch (FileAlreadyExistsException x) {
       
   762         }
       
   763         entry.delete();
       
   764         source.delete();
       
   765         target.delete();
       
   766 
       
   767         /*
       
   768          * Test: copy directory + attributes
       
   769          */
       
   770         source = createSourceDirectory(dir);
       
   771         target = getTargetFile(dir);
       
   772         copyAndVerify(source, target, COPY_ATTRIBUTES);
       
   773         source.delete();
       
   774         target.delete();
       
   775 
       
   776         // -- symbolic links --
       
   777 
       
   778         /**
       
   779          * Test: Follow link
       
   780          */
       
   781         if (supportsLinks) {
       
   782             source = createSourceFile(dir);
       
   783             link = dir.resolve("link").createSymbolicLink(source);
       
   784             target = getTargetFile(dir);
       
   785             copyAndVerify(link, target);
       
   786             link.delete();
       
   787             source.delete();
       
   788         }
       
   789 
       
   790         /**
       
   791          * Test: Copy link (to file)
       
   792          */
       
   793         if (supportsLinks) {
       
   794             source = createSourceFile(dir);
       
   795             link = dir.resolve("link").createSymbolicLink(source);
       
   796             target = getTargetFile(dir);
       
   797             copyAndVerify(link, target, NOFOLLOW_LINKS);
       
   798             link.delete();
       
   799             source.delete();
       
   800         }
       
   801 
       
   802         /**
       
   803          * Test: Copy link (to directory)
       
   804          */
       
   805         if (supportsLinks) {
       
   806             source = dir.resolve("mydir").createDirectory();
       
   807             link = dir.resolve("link").createSymbolicLink(source);
       
   808             target = getTargetFile(dir);
       
   809             copyAndVerify(link, target, NOFOLLOW_LINKS);
       
   810             link.delete();
       
   811             source.delete();
       
   812         }
       
   813 
       
   814         /**
       
   815          * Test: Copy broken link
       
   816          */
       
   817         if (supportsLinks) {
       
   818             assertTrue(source.notExists());
       
   819             link = dir.resolve("link").createSymbolicLink(source);
       
   820             target = getTargetFile(dir);
       
   821             copyAndVerify(link, target, NOFOLLOW_LINKS);
       
   822             link.delete();
       
   823         }
       
   824 
       
   825         /**
       
   826          * Test: Copy link to UNC (Windows only)
       
   827          */
       
   828         if (supportsLinks &&
       
   829             System.getProperty("os.name").startsWith("Windows"))
       
   830         {
       
   831             Path unc = Paths.get("\\\\rialto\\share\\file");
       
   832             link = dir.resolve("link").createSymbolicLink(unc);
       
   833             target = getTargetFile(dir);
       
   834             copyAndVerify(link, target, NOFOLLOW_LINKS);
       
   835             link.delete();
       
   836         }
       
   837 
       
   838         // -- misc. tests --
       
   839 
       
   840         /**
       
   841          * Test nulls
       
   842          */
       
   843         source = createSourceFile(dir);
       
   844         target = getTargetFile(dir);
       
   845         try {
       
   846             source.copyTo(null);
       
   847             throw new RuntimeException("NullPointerException expected");
       
   848         } catch (NullPointerException x) { }
       
   849         try {
       
   850             source.copyTo(target, (CopyOption[])null);
       
   851             throw new RuntimeException("NullPointerException expected");
       
   852         } catch (NullPointerException x) { }
       
   853         try {
       
   854             CopyOption[] opts = { REPLACE_EXISTING, null };
       
   855             source.copyTo(target, opts);
       
   856             throw new RuntimeException("NullPointerException expected");
       
   857         } catch (NullPointerException x) { }
       
   858         source.delete();
       
   859 
       
   860         /**
       
   861          * Test UOE
       
   862          */
       
   863         source = createSourceFile(dir);
       
   864         target = getTargetFile(dir);
       
   865         try {
       
   866             source.copyTo(target, new CopyOption() { });
       
   867         } catch (UnsupportedOperationException x) { }
       
   868         try {
       
   869             source.copyTo(target, REPLACE_EXISTING,  new CopyOption() { });
       
   870         } catch (UnsupportedOperationException x) { }
       
   871         source.delete();
       
   872     }
       
   873 
       
   874 
       
   875     static void assertTrue(boolean value) {
       
   876         if (!value)
       
   877             throw new RuntimeException("Assertion failed");
       
   878     }
       
   879 
       
   880     // computes simple hash of the given file
       
   881     static int computeHash(Path file) throws IOException {
       
   882         int h = 0;
       
   883 
       
   884         InputStream in = file.newInputStream();
       
   885         try {
       
   886             byte[] buf = new byte[1024];
       
   887             int n;
       
   888             do {
       
   889                 n = in.read(buf);
       
   890                 for (int i=0; i<n; i++) {
       
   891                     h = 31*h + (buf[i] & 0xff);
       
   892                 }
       
   893             } while (n > 0);
       
   894         } finally {
       
   895             in.close();
       
   896         }
       
   897         return h;
       
   898     }
       
   899 
       
   900     // create file of random size in given directory
       
   901     static Path createSourceFile(Path dir) throws IOException {
       
   902         String name = "source" + Integer.toString(rand.nextInt());
       
   903         Path file = dir.resolve(name).createFile();
       
   904         byte[] bytes = new byte[rand.nextInt(128*1024)];
       
   905         rand.nextBytes(bytes);
       
   906         OutputStream out = file.newOutputStream();
       
   907         try {
       
   908             out.write(bytes);
       
   909         } finally {
       
   910             out.close();
       
   911         }
       
   912         randomizeAttributes(file);
       
   913         return file;
       
   914     }
       
   915 
       
   916     // create directory in the given directory
       
   917     static Path createSourceDirectory(Path dir) throws IOException {
       
   918         String name = "sourcedir" + Integer.toString(rand.nextInt());
       
   919         Path subdir = dir.resolve(name).createDirectory();
       
   920         randomizeAttributes(subdir);
       
   921         return subdir;
       
   922     }
       
   923 
       
   924     // "randomize" the file attributes of the given file.
       
   925     static void randomizeAttributes(Path file) throws IOException {
       
   926         String os = System.getProperty("os.name");
       
   927         boolean isWindows = os.startsWith("Windows");
       
   928         boolean isUnix = os.equals("SunOS") || os.equals("Linux");
       
   929         boolean isDirectory = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS)
       
   930             .isDirectory();
       
   931 
       
   932         if (isUnix) {
       
   933             Set<PosixFilePermission> perms = Attributes
       
   934                 .readPosixFileAttributes(file, NOFOLLOW_LINKS).permissions();
       
   935             PosixFilePermission[] toChange = {
       
   936                 PosixFilePermission.GROUP_READ,
       
   937                 PosixFilePermission.GROUP_WRITE,
       
   938                 PosixFilePermission.GROUP_EXECUTE,
       
   939                 PosixFilePermission.OTHERS_READ,
       
   940                 PosixFilePermission.OTHERS_WRITE,
       
   941                 PosixFilePermission.OTHERS_EXECUTE
       
   942             };
       
   943             for (PosixFilePermission perm: toChange) {
       
   944                 if (heads()) {
       
   945                     perms.add(perm);
       
   946                 } else {
       
   947                     perms.remove(perm);
       
   948                 }
       
   949             }
       
   950             Attributes.setPosixFilePermissions(file, perms);
       
   951         }
       
   952 
       
   953         if (isWindows) {
       
   954             DosFileAttributeView view = file
       
   955                 .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS);
       
   956             // only set or unset the hidden attribute
       
   957             view.setHidden(heads());
       
   958         }
       
   959 
       
   960         boolean addUserDefinedFileAttributes = heads() &&
       
   961             file.getFileStore().supportsFileAttributeView("xattr");
       
   962 
       
   963         // remove this when copying a direcory copies its named streams
       
   964         if (isWindows && isDirectory) addUserDefinedFileAttributes = false;
       
   965 
       
   966         if (addUserDefinedFileAttributes) {
       
   967             UserDefinedFileAttributeView view = file
       
   968                 .getFileAttributeView(UserDefinedFileAttributeView.class);
       
   969             int n = rand.nextInt(16);
       
   970             while (n > 0) {
       
   971                 byte[] value = new byte[1 + rand.nextInt(100)];
       
   972                 view.write("user." + Integer.toString(n), ByteBuffer.wrap(value));
       
   973                 n--;
       
   974             }
       
   975         }
       
   976     }
       
   977 
       
   978     // create name for file in given directory
       
   979     static Path getTargetFile(Path dir) throws IOException {
       
   980         String name = "target" + Integer.toString(rand.nextInt());
       
   981         return dir.resolve(name);
       
   982     }
       
   983  }