test/tools/sjavac/SJavac.java

changeset 1504
22e417cdddee
child 1516
8943b4213f59
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/test/tools/sjavac/SJavac.java	Fri Jan 18 00:16:21 2013 +0100
     1.3 @@ -0,0 +1,590 @@
     1.4 +/*
     1.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + */
    1.26 +
    1.27 +/*
    1.28 + * @test
    1.29 + * @summary Test all aspects of sjavac.
    1.30 + *
    1.31 + * @bug 8004658
    1.32 + * @summary Add internal smart javac wrapper to solve JEP 139
    1.33 + *
    1.34 + * @run main SJavac
    1.35 + */
    1.36 +
    1.37 +import java.util.*;
    1.38 +import java.io.*;
    1.39 +import java.net.*;
    1.40 +import java.nio.file.*;
    1.41 +import java.nio.file.attribute.*;
    1.42 +import java.nio.charset.*;
    1.43 +
    1.44 +import com.sun.tools.sjavac.Main;
    1.45 +
    1.46 +public
    1.47 +class SJavac {
    1.48 +
    1.49 +    public static void main(String... args) throws Exception {
    1.50 +        URL url = SJavac.class.getClassLoader().getResource("com/sun/tools/sjavac/Main.class");
    1.51 +        if (url == null) {
    1.52 +            // No sjavac in the classpath.
    1.53 +            System.out.println("pass by default");
    1.54 +            return;
    1.55 +        }
    1.56 +
    1.57 +        SJavac s = new SJavac();
    1.58 +        s.test();
    1.59 +    }
    1.60 +
    1.61 +    FileSystem defaultfs = FileSystems.getDefault();
    1.62 +
    1.63 +    // Where to put generated sources that will
    1.64 +    // test aspects of sjavac, ie JTWork/scratch/gensrc
    1.65 +    Path gensrc;
    1.66 +    // More gensrc dirs are used to test merging of serveral source roots.
    1.67 +    Path gensrc2;
    1.68 +    Path gensrc3;
    1.69 +
    1.70 +    // Where to put compiled classes.
    1.71 +    Path bin;
    1.72 +    // Where to put c-header files.
    1.73 +    Path headers;
    1.74 +
    1.75 +    // The sjavac compiler.
    1.76 +    Main main = new Main();
    1.77 +
    1.78 +    // Remember the previous bin and headers state here.
    1.79 +    Map<String,Long> previous_bin_state;
    1.80 +    Map<String,Long> previous_headers_state;
    1.81 +
    1.82 +    public void test() throws Exception {
    1.83 +        gensrc = defaultfs.getPath("gensrc");
    1.84 +        gensrc2 = defaultfs.getPath("gensrc2");
    1.85 +        gensrc3 = defaultfs.getPath("gensrc3");
    1.86 +        bin = defaultfs.getPath("bin");
    1.87 +        headers = defaultfs.getPath("headers");
    1.88 +
    1.89 +        Files.createDirectory(gensrc);
    1.90 +        Files.createDirectory(gensrc2);
    1.91 +        Files.createDirectory(gensrc3);
    1.92 +        Files.createDirectory(bin);
    1.93 +        Files.createDirectory(headers);
    1.94 +
    1.95 +        initialCompile();
    1.96 +        incrementalCompileNoChanges();
    1.97 +        incrementalCompileDroppingClasses();
    1.98 +        incrementalCompileWithChange();
    1.99 +        incrementalCompileDropAllNatives();
   1.100 +        incrementalCompileAddNative();
   1.101 +        incrementalCompileChangeNative();
   1.102 +        compileWithOverrideSource();
   1.103 +        compileWithInvisibleSources();
   1.104 +        compileCircularSources();
   1.105 +
   1.106 +        delete(gensrc);
   1.107 +        delete(gensrc2);
   1.108 +        delete(gensrc3);
   1.109 +        delete(bin);
   1.110 +    }
   1.111 +
   1.112 +    void initialCompile() throws Exception {
   1.113 +        System.out.println("\nInitial compile of gensrc.");
   1.114 +        System.out.println("----------------------------");
   1.115 +        populate(gensrc,
   1.116 +            "alfa/AINT.java",
   1.117 +            "package alfa; public interface AINT { void aint(); }",
   1.118 +
   1.119 +            "alfa/A.java",
   1.120 +            "package alfa; public class A implements AINT { "+
   1.121 +                 "public final static int DEFINITION = 17; public void aint() { } }",
   1.122 +
   1.123 +            "alfa/AA.java",
   1.124 +            "package alfa;"+
   1.125 +            "// A package private class, not contributing to the public api.\n"+
   1.126 +            "class AA {"+
   1.127 +            "   // A properly nested static inner class.\n"+
   1.128 +            "    static class AAA { }\n"+
   1.129 +            "    // A properly nested inner class.\n"+
   1.130 +            "    class AAAA { }\n"+
   1.131 +            "    Runnable foo() {\n"+
   1.132 +            "        // A proper anonymous class.\n"+
   1.133 +            "        return new Runnable() { public void run() { } };\n"+
   1.134 +            "    }\n"+
   1.135 +            "    AAA aaa;\n"+
   1.136 +            "    AAAA aaaa;\n"+
   1.137 +            "    AAAAA aaaaa;\n"+
   1.138 +            "}\n"+
   1.139 +            "class AAAAA {\n"+
   1.140 +            "    // A bad auxiliary class, but no one is referencing it\n"+
   1.141 +            "    // from outside of this source file, therefore it is ok.\n"+
   1.142 +            "}\n",
   1.143 +
   1.144 +            "beta/BINT.java",
   1.145 +            "package beta;public interface BINT { void foo(); }",
   1.146 +
   1.147 +            "beta/B.java",
   1.148 +            "package beta; import alfa.A; public class B {"+
   1.149 +            "private int b() { return A.DEFINITION; } native void foo(); }");
   1.150 +
   1.151 +        compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
   1.152 +                "--server:portfile=testserver,background=false", "--log=debug");
   1.153 +        previous_bin_state = collectState(bin);
   1.154 +        previous_headers_state = collectState(headers);
   1.155 +    }
   1.156 +
   1.157 +    void incrementalCompileNoChanges() throws Exception {
   1.158 +        System.out.println("\nTesting that no change in sources implies no change in binaries.");
   1.159 +        System.out.println("------------------------------------------------------------------");
   1.160 +        compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
   1.161 +                "--server:portfile=testserver,background=false", "--log=debug");
   1.162 +        Map<String,Long> new_bin_state = collectState(bin);
   1.163 +        verifyEqual(new_bin_state, previous_bin_state);
   1.164 +        Map<String,Long> new_headers_state = collectState(headers);
   1.165 +        verifyEqual(previous_headers_state, new_headers_state);
   1.166 +    }
   1.167 +
   1.168 +    void incrementalCompileDroppingClasses() throws Exception {
   1.169 +        System.out.println("\nTesting that deleting AA.java deletes all");
   1.170 +        System.out.println("generated inner class as well as AA.class");
   1.171 +        System.out.println("-----------------------------------------");
   1.172 +        removeFrom(gensrc, "alfa/AA.java");
   1.173 +        compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
   1.174 +                "--server:portfile=testserver,background=false", "--log=debug");
   1.175 +        Map<String,Long> new_bin_state = collectState(bin);
   1.176 +        verifyThatFilesHaveBeenRemoved(previous_bin_state, new_bin_state,
   1.177 +                                       "bin/alfa/AA$1.class",
   1.178 +                                       "bin/alfa/AA$AAAA.class",
   1.179 +                                       "bin/alfa/AA$AAA.class",
   1.180 +                                       "bin/alfa/AAAAA.class",
   1.181 +                                       "bin/alfa/AA.class");
   1.182 +
   1.183 +        previous_bin_state = new_bin_state;
   1.184 +        Map<String,Long> new_headers_state = collectState(headers);
   1.185 +        verifyEqual(previous_headers_state, new_headers_state);
   1.186 +    }
   1.187 +
   1.188 +    void incrementalCompileWithChange() throws Exception {
   1.189 +        System.out.println("\nNow update the A.java file with a new timestamps and");
   1.190 +        System.out.println("new final static definition. This should trigger a recompile,");
   1.191 +        System.out.println("not only of alfa, but also beta.");
   1.192 +        System.out.println("But check that the generated native header was not updated!");
   1.193 +        System.out.println("Since we did not modify the native api of B.");
   1.194 +        System.out.println("-------------------------------------------------------------");
   1.195 +
   1.196 +        populate(gensrc,"alfa/A.java",
   1.197 +                       "package alfa; public class A implements AINT { "+
   1.198 +                 "public final static int DEFINITION = 18; public void aint() { } private void foo() { } }");
   1.199 +
   1.200 +        compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
   1.201 +                "--server:portfile=testserver,background=false", "--log=debug");
   1.202 +        Map<String,Long> new_bin_state = collectState(bin);
   1.203 +
   1.204 +        verifyNewerFiles(previous_bin_state, new_bin_state,
   1.205 +                         "bin/alfa/A.class",
   1.206 +                         "bin/alfa/AINT.class",
   1.207 +                         "bin/beta/B.class",
   1.208 +                         "bin/beta/BINT.class",
   1.209 +                         "bin/javac_state");
   1.210 +        previous_bin_state = new_bin_state;
   1.211 +
   1.212 +        Map<String,Long> new_headers_state = collectState(headers);
   1.213 +        verifyEqual(new_headers_state, previous_headers_state);
   1.214 +    }
   1.215 +
   1.216 +    void incrementalCompileDropAllNatives() throws Exception {
   1.217 +        System.out.println("\nNow update the B.java file with one less native method,");
   1.218 +        System.out.println("ie it has no longer any methods!");
   1.219 +        System.out.println("Verify that beta_B.h is removed!");
   1.220 +        System.out.println("---------------------------------------------------------");
   1.221 +
   1.222 +        populate(gensrc,"beta/B.java",
   1.223 +                       "package beta; import alfa.A; public class B {"+
   1.224 +                       "private int b() { return A.DEFINITION; } }");
   1.225 +
   1.226 +        compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
   1.227 +                "--server:portfile=testserver,background=false", "--log=debug");
   1.228 +        Map<String,Long> new_bin_state = collectState(bin);
   1.229 +        verifyNewerFiles(previous_bin_state, new_bin_state,
   1.230 +                         "bin/beta/B.class",
   1.231 +                         "bin/beta/BINT.class",
   1.232 +                         "bin/javac_state");
   1.233 +        previous_bin_state = new_bin_state;
   1.234 +
   1.235 +        Map<String,Long> new_headers_state = collectState(headers);
   1.236 +        verifyThatFilesHaveBeenRemoved(previous_headers_state, new_headers_state,
   1.237 +                                       "headers/beta_B.h");
   1.238 +        previous_headers_state = new_headers_state;
   1.239 +    }
   1.240 +
   1.241 +    void incrementalCompileAddNative() throws Exception {
   1.242 +        System.out.println("\nNow update the B.java file with a final static annotated with @Native.");
   1.243 +        System.out.println("Verify that beta_B.h is added again!");
   1.244 +        System.out.println("------------------------------------------------------------------------");
   1.245 +
   1.246 +        populate(gensrc,"beta/B.java",
   1.247 +                       "package beta; import alfa.A; public class B {"+
   1.248 +                       "private int b() { return A.DEFINITION; } "+
   1.249 +                 "@java.lang.annotation.Native final static int alfa = 42; }");
   1.250 +
   1.251 +        compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
   1.252 +                "--server:portfile=testserver,background=false", "--log=debug");
   1.253 +        Map<String,Long> new_bin_state = collectState(bin);
   1.254 +        verifyNewerFiles(previous_bin_state, new_bin_state,
   1.255 +                         "bin/beta/B.class",
   1.256 +                         "bin/beta/BINT.class",
   1.257 +                         "bin/javac_state");
   1.258 +        previous_bin_state = new_bin_state;
   1.259 +
   1.260 +        Map<String,Long> new_headers_state = collectState(headers);
   1.261 +        verifyThatFilesHaveBeenAdded(previous_headers_state, new_headers_state,
   1.262 +                                     "headers/beta_B.h");
   1.263 +        previous_headers_state = new_headers_state;
   1.264 +    }
   1.265 +
   1.266 +    void incrementalCompileChangeNative() throws Exception {
   1.267 +        System.out.println("\nNow update the B.java file with a new value for the final static"+
   1.268 +                           " annotated with @Native.");
   1.269 +        System.out.println("Verify that beta_B.h is rewritten again!");
   1.270 +        System.out.println("-------------------------------------------------------------------");
   1.271 +
   1.272 +        populate(gensrc,"beta/B.java",
   1.273 +                       "package beta; import alfa.A; public class B {"+
   1.274 +                       "private int b() { return A.DEFINITION; } "+
   1.275 +                 "@java.lang.annotation.Native final static int alfa = 43; }");
   1.276 +
   1.277 +        compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1",
   1.278 +                "--server:portfile=testserver,background=false", "--log=debug");
   1.279 +        Map<String,Long> new_bin_state = collectState(bin);
   1.280 +        verifyNewerFiles(previous_bin_state, new_bin_state,
   1.281 +                         "bin/beta/B.class",
   1.282 +                         "bin/beta/BINT.class",
   1.283 +                         "bin/javac_state");
   1.284 +        previous_bin_state = new_bin_state;
   1.285 +
   1.286 +        Map<String,Long> new_headers_state = collectState(headers);
   1.287 +        verifyNewerFiles(previous_headers_state, new_headers_state,
   1.288 +                         "headers/beta_B.h");
   1.289 +        previous_headers_state = new_headers_state;
   1.290 +    }
   1.291 +
   1.292 +    void compileWithOverrideSource() throws Exception {
   1.293 +        System.out.println("\nNow verify that we can override sources to be compiled.");
   1.294 +        System.out.println("Compile gensrc and gensrc2. However do not compile broken beta.B in gensrc,");
   1.295 +        System.out.println("only compile ok beta.B in gensrc2.");
   1.296 +        System.out.println("---------------------------------------------------------------------------");
   1.297 +
   1.298 +        delete(gensrc);
   1.299 +        delete(gensrc2);
   1.300 +        delete(bin);
   1.301 +        previous_bin_state = collectState(bin);
   1.302 +
   1.303 +        populate(gensrc,"alfa/A.java",
   1.304 +                 "package alfa; import beta.B; import gamma.C; public class A { B b; C c; }",
   1.305 +                 "beta/B.java",
   1.306 +                 "package beta; public class B { broken",
   1.307 +                 "gamma/C.java",
   1.308 +                 "package gamma; public class C { }");
   1.309 +
   1.310 +        populate(gensrc2,
   1.311 +                 "beta/B.java",
   1.312 +                 "package beta; public class B { }");
   1.313 +
   1.314 +        compile("-x", "beta", "gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1",
   1.315 +                "--server:portfile=testserver,background=false");
   1.316 +        Map<String,Long> new_bin_state = collectState(bin);
   1.317 +        verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
   1.318 +                                     "bin/alfa/A.class",
   1.319 +                                     "bin/beta/B.class",
   1.320 +                                     "bin/gamma/C.class",
   1.321 +                                     "bin/javac_state");
   1.322 +
   1.323 +        System.out.println("----- Compile with exluded beta went well!");
   1.324 +        delete(bin);
   1.325 +        compileExpectFailure("gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1",
   1.326 +                             "--server:portfile=testserver,background=false");
   1.327 +
   1.328 +        System.out.println("----- Compile without exluded beta failed, as expected! Good!");
   1.329 +        delete(bin);
   1.330 +    }
   1.331 +
   1.332 +    void compileWithInvisibleSources() throws Exception {
   1.333 +        System.out.println("\nNow verify that we can make sources invisible to linking (sourcepath).");
   1.334 +        System.out.println("Compile gensrc and link against gensrc2 and gensrc3, however");
   1.335 +        System.out.println("gensrc2 contains broken code in beta.B, thus we must exclude that package");
   1.336 +        System.out.println("fortunately gensrc3 contains a proper beta.B.");
   1.337 +        System.out.println("------------------------------------------------------------------------");
   1.338 +
   1.339 +        // Start with a fresh gensrcs and bin.
   1.340 +        delete(gensrc);
   1.341 +        delete(gensrc2);
   1.342 +        delete(gensrc3);
   1.343 +        delete(bin);
   1.344 +        previous_bin_state = collectState(bin);
   1.345 +
   1.346 +        populate(gensrc,"alfa/A.java",
   1.347 +                 "package alfa; import beta.B; import gamma.C; public class A { B b; C c; }");
   1.348 +        populate(gensrc2,"beta/B.java",
   1.349 +                 "package beta; public class B { broken",
   1.350 +                 "gamma/C.java",
   1.351 +                 "package gamma; public class C { }");
   1.352 +        populate(gensrc3, "beta/B.java",
   1.353 +                 "package beta; public class B { }");
   1.354 +
   1.355 +        compile("gensrc", "-x", "beta", "-sourcepath", "gensrc2",
   1.356 +                "-sourcepath", "gensrc3", "-d", "bin", "-h", "headers", "-j", "1",
   1.357 +                "--server:portfile=testserver,background=false");
   1.358 +
   1.359 +        System.out.println("The first compile went well!");
   1.360 +        Map<String,Long> new_bin_state = collectState(bin);
   1.361 +        verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
   1.362 +                                     "bin/alfa/A.class",
   1.363 +                                     "bin/javac_state");
   1.364 +
   1.365 +        System.out.println("----- Compile with exluded beta went well!");
   1.366 +        delete(bin);
   1.367 +        compileExpectFailure("gensrc", "-sourcepath", "gensrc2", "-sourcepath", "gensrc3",
   1.368 +                             "-d", "bin", "-h", "headers", "-j", "1",
   1.369 +                             "--server:portfile=testserver,background=false");
   1.370 +
   1.371 +        System.out.println("----- Compile without exluded beta failed, as expected! Good!");
   1.372 +        delete(bin);
   1.373 +    }
   1.374 +
   1.375 +    void compileCircularSources() throws Exception {
   1.376 +        System.out.println("\nNow verify that circular sources split on multiple cores can be compiled.");
   1.377 +        System.out.println("---------------------------------------------------------------------------");
   1.378 +
   1.379 +        // Start with a fresh gensrcs and bin.
   1.380 +        delete(gensrc);
   1.381 +        delete(gensrc2);
   1.382 +        delete(gensrc3);
   1.383 +        delete(bin);
   1.384 +        previous_bin_state = collectState(bin);
   1.385 +
   1.386 +        populate(gensrc,"alfa/A.java",
   1.387 +                 "package alfa; public class A { beta.B b; }",
   1.388 +                 "beta/B.java",
   1.389 +                 "package beta; public class B { gamma.C c; }",
   1.390 +                 "gamma/C.java",
   1.391 +                 "package gamma; public class C { alfa.A a; }");
   1.392 +
   1.393 +        compile("gensrc", "-d", "bin", "-h", "headers", "-j", "3",
   1.394 +                "--server:portfile=testserver,background=false","--log=debug");
   1.395 +        Map<String,Long> new_bin_state = collectState(bin);
   1.396 +        verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state,
   1.397 +                                     "bin/alfa/A.class",
   1.398 +                                     "bin/beta/B.class",
   1.399 +                                     "bin/gamma/C.class",
   1.400 +                                     "bin/javac_state");
   1.401 +        delete(bin);
   1.402 +    }
   1.403 +
   1.404 +    void removeFrom(Path dir, String... args) throws IOException {
   1.405 +        for (String filename : args) {
   1.406 +            Path p = dir.resolve(filename);
   1.407 +            Files.delete(p);
   1.408 +        }
   1.409 +    }
   1.410 +
   1.411 +    void populate(Path src, String... args) throws IOException {
   1.412 +        if (!Files.exists(src)) {
   1.413 +            Files.createDirectory(src);
   1.414 +        }
   1.415 +        String[] a = args;
   1.416 +        for (int i = 0; i<a.length; i+=2) {
   1.417 +            String filename = a[i];
   1.418 +            String content = a[i+1];
   1.419 +            Path p = src.resolve(filename);
   1.420 +            Files.createDirectories(p.getParent());
   1.421 +            PrintWriter out = new PrintWriter(Files.newBufferedWriter(p,
   1.422 +                                                                      Charset.defaultCharset()));
   1.423 +            out.println(content);
   1.424 +            out.close();
   1.425 +        }
   1.426 +    }
   1.427 +
   1.428 +    void delete(Path root) throws IOException {
   1.429 +        if (!Files.exists(root)) return;
   1.430 +        Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
   1.431 +                 @Override
   1.432 +                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
   1.433 +                 {
   1.434 +                     Files.delete(file);
   1.435 +                     return FileVisitResult.CONTINUE;
   1.436 +                 }
   1.437 +
   1.438 +                 @Override
   1.439 +                 public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException
   1.440 +                 {
   1.441 +                     if (e == null) {
   1.442 +                         if (!dir.equals(root)) Files.delete(dir);
   1.443 +                         return FileVisitResult.CONTINUE;
   1.444 +                     } else {
   1.445 +                         // directory iteration failed
   1.446 +                         throw e;
   1.447 +                     }
   1.448 +                 }
   1.449 +            });
   1.450 +    }
   1.451 +
   1.452 +    void compile(String... args) throws Exception {
   1.453 +        int rc = main.go(args, System.out, System.err);
   1.454 +        if (rc != 0) throw new Exception("Error during compile!");
   1.455 +
   1.456 +        // Wait a second, to get around the (temporary) problem with
   1.457 +        // second resolution in the Java file api. But do not do this
   1.458 +        // on windows where the timestamps work.
   1.459 +        long in_a_sec = System.currentTimeMillis()+1000;
   1.460 +        while (in_a_sec > System.currentTimeMillis()) {
   1.461 +            try {
   1.462 +                Thread.sleep(1000);
   1.463 +            } catch (InterruptedException e) {
   1.464 +            }
   1.465 +        }
   1.466 +    }
   1.467 +
   1.468 +    void compileExpectFailure(String... args) throws Exception {
   1.469 +        int rc = main.go(args, System.out, System.err);
   1.470 +        if (rc == 0) throw new Exception("Expected error during compile! Did not fail!");
   1.471 +    }
   1.472 +
   1.473 +    Map<String,Long> collectState(Path dir) throws IOException
   1.474 +    {
   1.475 +        final Map<String,Long> files = new HashMap<>();
   1.476 +        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
   1.477 +                 @Override
   1.478 +                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
   1.479 +                   throws IOException
   1.480 +                 {
   1.481 +                     files.put(file.toString(),new Long(Files.getLastModifiedTime(file).toMillis()));
   1.482 +                     return FileVisitResult.CONTINUE;
   1.483 +                 }
   1.484 +            });
   1.485 +        return files;
   1.486 +    }
   1.487 +
   1.488 +    void verifyThatFilesHaveBeenRemoved(Map<String,Long> from,
   1.489 +                                        Map<String,Long> to,
   1.490 +                                        String... args) throws Exception {
   1.491 +
   1.492 +        Set<String> froms = from.keySet();
   1.493 +        Set<String> tos = to.keySet();
   1.494 +
   1.495 +        if (froms.equals(tos)) {
   1.496 +            throw new Exception("Expected new state to have fewer files than previous state!");
   1.497 +        }
   1.498 +
   1.499 +        for (String t : tos) {
   1.500 +            if (!froms.contains(t)) {
   1.501 +                throw new Exception("Expected "+t+" to exist in previous state!");
   1.502 +            }
   1.503 +        }
   1.504 +
   1.505 +        for (String f : args) {
   1.506 +            f = f.replace("/", File.separator);
   1.507 +            if (!froms.contains(f)) {
   1.508 +                throw new Exception("Expected "+f+" to exist in previous state!");
   1.509 +            }
   1.510 +            if (tos.contains(f)) {
   1.511 +                throw new Exception("Expected "+f+" to have been removed from the new state!");
   1.512 +            }
   1.513 +        }
   1.514 +
   1.515 +        if (froms.size() - args.length != tos.size()) {
   1.516 +            throw new Exception("There are more removed files than the expected list!");
   1.517 +        }
   1.518 +    }
   1.519 +
   1.520 +    void verifyThatFilesHaveBeenAdded(Map<String,Long> from,
   1.521 +                                      Map<String,Long> to,
   1.522 +                                      String... args) throws Exception {
   1.523 +
   1.524 +        Set<String> froms = from.keySet();
   1.525 +        Set<String> tos = to.keySet();
   1.526 +
   1.527 +        if (froms.equals(tos)) {
   1.528 +            throw new Exception("Expected new state to have more files than previous state!");
   1.529 +        }
   1.530 +
   1.531 +        for (String t : froms) {
   1.532 +            if (!tos.contains(t)) {
   1.533 +                throw new Exception("Expected "+t+" to exist in new state!");
   1.534 +            }
   1.535 +        }
   1.536 +
   1.537 +        for (String f : args) {
   1.538 +            f = f.replace("/", File.separator);
   1.539 +            if (!tos.contains(f)) {
   1.540 +                throw new Exception("Expected "+f+" to have been added to new state!");
   1.541 +            }
   1.542 +            if (froms.contains(f)) {
   1.543 +                throw new Exception("Expected "+f+" to not exist in previous state!");
   1.544 +            }
   1.545 +        }
   1.546 +
   1.547 +        if (froms.size() + args.length != tos.size()) {
   1.548 +            throw new Exception("There are more added files than the expected list!");
   1.549 +        }
   1.550 +    }
   1.551 +
   1.552 +    void verifyNewerFiles(Map<String,Long> from,
   1.553 +                          Map<String,Long> to,
   1.554 +                          String... args) throws Exception {
   1.555 +        if (!from.keySet().equals(to.keySet())) {
   1.556 +            throw new Exception("Expected the set of files to be identical!");
   1.557 +        }
   1.558 +        Set<String> files = new HashSet<String>();
   1.559 +        for (String s : args) {
   1.560 +            files.add(s.replace("/", File.separator));
   1.561 +        }
   1.562 +        for (String fn : from.keySet()) {
   1.563 +            long f = from.get(fn);
   1.564 +            long t = to.get(fn);
   1.565 +            if (files.contains(fn)) {
   1.566 +                if (t <= f) {
   1.567 +                    throw new Exception("Expected "+fn+" to have a more recent timestamp!");
   1.568 +                }
   1.569 +            } else {
   1.570 +                if (t != f) {
   1.571 +                    throw new Exception("Expected "+fn+" to have the same timestamp!");
   1.572 +                }
   1.573 +            }
   1.574 +        }
   1.575 +    }
   1.576 +
   1.577 +    String print(Map<String,Long> m) {
   1.578 +        StringBuilder b = new StringBuilder();
   1.579 +        Set<String> keys = m.keySet();
   1.580 +        for (String k : keys) {
   1.581 +            b.append(k+" "+m.get(k)+"\n");
   1.582 +        }
   1.583 +        return b.toString();
   1.584 +    }
   1.585 +
   1.586 +    void verifyEqual(Map<String,Long> from, Map<String,Long> to) throws Exception {
   1.587 +        if (!from.equals(to)) {
   1.588 +            System.out.println("FROM---"+print(from));
   1.589 +            System.out.println("TO-----"+print(to));
   1.590 +            throw new Exception("The dir should not differ! But it does!");
   1.591 +        }
   1.592 +    }
   1.593 +}

mercurial