SJavacTester.java revision 3219:aacc4ceb35c9
1/*
2 * Copyright (c) 2014, 2016, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24import java.util.*;
25import java.io.*;
26import java.nio.file.*;
27import java.nio.file.attribute.*;
28
29import com.sun.tools.sjavac.Main;
30
31public class SJavacTester {
32
33    final ToolBox tb = new ToolBox();
34    final Path TEST_ROOT = Paths.get(getClass().getSimpleName());
35
36    // Generated sources that will test aspects of sjavac
37    final Path GENSRC = TEST_ROOT.resolve("gensrc");
38    // Gensrc dirs used to test merging of serveral source roots.
39    final Path GENSRC2 = TEST_ROOT.resolve("gensrc2");
40    final Path GENSRC3 = TEST_ROOT.resolve("gensrc3");
41
42    // Dir for compiled classes.
43    final Path BIN = TEST_ROOT.resolve("bin");
44    // Dir for c-header files.
45    final Path HEADERS = TEST_ROOT.resolve("headers");
46
47    // Remember the previous bin and headers state here.
48    Map<String,Long> previous_bin_state;
49    Map<String,Long> previous_headers_state;
50
51    void initialCompile() throws Exception {
52        System.out.println("\nInitial compile of gensrc.");
53        tb.writeFile(GENSRC.resolve("alfa/omega/AINT.java"),
54                     "package alfa.omega; public interface AINT { void aint(); }");
55        tb.writeFile(GENSRC.resolve("alfa/omega/A.java"),
56                     "package alfa.omega; public class A implements AINT { "+
57                     "public final static int DEFINITION = 17; public void aint() { } }");
58        tb.writeFile(GENSRC.resolve("alfa/omega/AA.java"),
59            "package alfa.omega;"+
60            "// A package private class, not contributing to the public api.\n"+
61            "class AA {"+
62            "   // A properly nested static inner class.\n"+
63            "    static class AAA { }\n"+
64            "    // A properly nested inner class.\n"+
65            "    class AAAA { }\n"+
66            "    Runnable foo() {\n"+
67            "        // A proper anonymous class.\n"+
68            "        return new Runnable() { public void run() { } };\n"+
69            "    }\n"+
70            "    AAA aaa;\n"+
71            "    AAAA aaaa;\n"+
72            "    AAAAA aaaaa;\n"+
73            "}\n"+
74            "class AAAAA {\n"+
75            "    // A bad auxiliary class, but no one is referencing it\n"+
76            "    // from outside of this source file, therefore it is ok.\n"+
77            "}\n");
78        tb.writeFile(GENSRC.resolve("beta/BINT.java"),
79                     "package beta;public interface BINT { void foo(); }");
80        tb.writeFile(GENSRC.resolve("beta/B.java"),
81                     "package beta; import alfa.omega.A; public class B {"+
82                     "private int b() { return A.DEFINITION; } native void foo(); }");
83
84        compile(GENSRC.toString(),
85                "-d", BIN.toString(),
86                "--state-dir=" + BIN,
87                "-h", HEADERS.toString(),
88                "-j", "1",
89                "--log=debug");
90    }
91
92    void removeFrom(Path dir, String... args) throws IOException {
93        for (String filename : args) {
94            Path p = dir.resolve(filename);
95            Files.delete(p);
96        }
97    }
98
99    void compile(String... args) throws Exception {
100        int rc = Main.go(args);
101        if (rc != 0) throw new Exception("Error during compile!");
102
103        // Wait a second, to get around the (temporary) problem with
104        // second resolution in the Java file api. But do not do this
105        // on windows where the timestamps work.
106        long in_a_sec = System.currentTimeMillis()+1000;
107        while (in_a_sec > System.currentTimeMillis()) {
108            try {
109                Thread.sleep(1000);
110            } catch (InterruptedException e) {
111            }
112        }
113    }
114
115    void compileExpectFailure(String... args) throws Exception {
116        int rc = Main.go(args);
117        if (rc == 0) throw new Exception("Expected error during compile! Did not fail!");
118    }
119
120    Map<String,Long> collectState(Path dir) throws IOException {
121        final Map<String,Long> files = new HashMap<>();
122        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
123                 @Override
124                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
125                   throws IOException
126                 {
127                     files.put(file.toString(),new Long(Files.getLastModifiedTime(file).toMillis()));
128                     return FileVisitResult.CONTINUE;
129                 }
130            });
131        return files;
132    }
133
134    void verifyThatFilesHaveBeenRemoved(Map<String,Long> from,
135                                        Map<String,Long> to,
136                                        String... args) throws Exception {
137
138        Set<String> froms = from.keySet();
139        Set<String> tos = to.keySet();
140
141        if (froms.equals(tos)) {
142            throw new Exception("Expected new state to have fewer files than previous state!");
143        }
144
145        for (String t : tos) {
146            if (!froms.contains(t)) {
147                throw new Exception("Expected "+t+" to exist in previous state!");
148            }
149        }
150
151        for (String f : args) {
152            f = f.replace("/", File.separator);
153            if (!froms.contains(f)) {
154                throw new Exception("Expected "+f+" to exist in previous state!");
155            }
156            if (tos.contains(f)) {
157                throw new Exception("Expected "+f+" to have been removed from the new state!");
158            }
159        }
160
161        if (froms.size() - args.length != tos.size()) {
162            throw new Exception("There are more removed files than the expected list!");
163        }
164    }
165
166    void verifyThatFilesHaveBeenAdded(Map<String,Long> from,
167                                      Map<String,Long> to,
168                                      String... args) throws Exception {
169
170        Set<String> froms = from.keySet();
171        Set<String> tos = to.keySet();
172
173        if (froms.equals(tos)) {
174            throw new Exception("Expected new state to have more files than previous state!");
175        }
176
177        for (String t : froms) {
178            if (!tos.contains(t)) {
179                throw new Exception("Expected "+t+" to exist in new state!");
180            }
181        }
182
183        for (String f : args) {
184            f = f.replace("/", File.separator);
185            if (!tos.contains(f)) {
186                throw new Exception("Expected "+f+" to have been added to new state!");
187            }
188            if (froms.contains(f)) {
189                throw new Exception("Expected "+f+" to not exist in previous state!");
190            }
191        }
192
193        if (froms.size() + args.length != tos.size()) {
194            throw new Exception("There are more added files than the expected list!");
195        }
196    }
197
198    void verifyNewerFiles(Map<String,Long> from,
199                          Map<String,Long> to,
200                          String... args) throws Exception {
201        if (!from.keySet().equals(to.keySet())) {
202            throw new Exception("Expected the set of files to be identical!");
203        }
204        Set<String> files = new HashSet<String>();
205        for (String s : args) {
206            files.add(s.replace("/", File.separator));
207        }
208        for (String fn : from.keySet()) {
209            long f = from.get(fn);
210            long t = to.get(fn);
211            if (files.contains(fn)) {
212                if (t <= f) {
213                    throw new Exception("Expected "+fn+" to have a more recent timestamp!");
214                }
215            } else {
216                if (t != f) {
217                    throw new Exception("Expected "+fn+" to have the same timestamp!");
218                }
219            }
220        }
221    }
222
223    String print(Map<String,Long> m) {
224        StringBuilder b = new StringBuilder();
225        Set<String> keys = m.keySet();
226        for (String k : keys) {
227            b.append(k+" "+m.get(k)+"\n");
228        }
229        return b.toString();
230    }
231
232    void verifyEqual(Map<String,Long> from, Map<String,Long> to) throws Exception {
233        if (!from.equals(to)) {
234            System.out.println("FROM---"+print(from));
235            System.out.println("TO-----"+print(to));
236            throw new Exception("The dir should not differ! But it does!");
237        }
238    }
239}
240