test/tools/javac/nativeHeaders/NativeHeaderTest.java

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 1723
a2889739cf21
parent 0
959103a6100f
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 */
aoqi@0 23
aoqi@0 24 /*
aoqi@0 25 * @test
aoqi@0 26 * @bug 7150368 8003412 8000407
aoqi@0 27 * @summary javac should include basic ability to generate native headers
aoqi@0 28 */
aoqi@0 29
aoqi@0 30 import java.io.File;
aoqi@0 31 import java.io.FileWriter;
aoqi@0 32 import java.io.IOException;
aoqi@0 33 import java.lang.annotation.Annotation;
aoqi@0 34 import java.lang.annotation.Retention;
aoqi@0 35 import java.lang.annotation.RetentionPolicy;
aoqi@0 36 import java.lang.reflect.InvocationTargetException;
aoqi@0 37 import java.lang.reflect.Method;
aoqi@0 38 import java.util.ArrayList;
aoqi@0 39 import java.util.Arrays;
aoqi@0 40 import java.util.HashSet;
aoqi@0 41 import java.util.List;
aoqi@0 42 import java.util.Set;
aoqi@0 43
aoqi@0 44 import javax.tools.StandardJavaFileManager;
aoqi@0 45 import javax.tools.StandardLocation;
aoqi@0 46
aoqi@0 47 import com.sun.source.util.JavacTask;
aoqi@0 48 import com.sun.tools.javac.api.JavacTool;
aoqi@0 49
aoqi@0 50 public class NativeHeaderTest {
aoqi@0 51 public static void main(String... args) throws Exception {
aoqi@0 52 new NativeHeaderTest().run();
aoqi@0 53 }
aoqi@0 54
aoqi@0 55 /** How to invoke javac. */
aoqi@0 56 enum RunKind {
aoqi@0 57 /** Use the command line entry point. */
aoqi@0 58 CMD,
aoqi@0 59 /** Use the JavaCompiler API. */
aoqi@0 60 API
aoqi@0 61 };
aoqi@0 62
aoqi@0 63 /** Which classes for which to generate headers. */
aoqi@0 64 enum GenKind {
aoqi@0 65 /** Just classes with native methods or the marker annotation. */
aoqi@0 66 SIMPLE,
aoqi@0 67 /** All appropriate classes within the top level class. */
aoqi@0 68 FULL
aoqi@0 69 };
aoqi@0 70
aoqi@0 71 // ---------- Test cases, invoked reflectively via run. ----------
aoqi@0 72
aoqi@0 73 @Test
aoqi@0 74 void simpleTest(RunKind rk, GenKind gk) throws Exception {
aoqi@0 75 List<File> files = new ArrayList<File>();
aoqi@0 76 files.add(createFile("p/C.java",
aoqi@0 77 "class C { native void m(); }"));
aoqi@0 78
aoqi@0 79 Set<String> expect = createSet("C.h");
aoqi@0 80
aoqi@0 81 test(rk, gk, files, expect);
aoqi@0 82 }
aoqi@0 83
aoqi@0 84 @Test
aoqi@0 85 void nestedClassTest(RunKind rk, GenKind gk) throws Exception {
aoqi@0 86 List<File> files = new ArrayList<File>();
aoqi@0 87 files.add(createFile("p/C.java",
aoqi@0 88 "class C { static class Inner { native void m(); } }"));
aoqi@0 89
aoqi@0 90 Set<String> expect = createSet("C_Inner.h");
aoqi@0 91 if (gk == GenKind.FULL) expect.add("C.h");
aoqi@0 92
aoqi@0 93 test(rk, gk, files, expect);
aoqi@0 94 }
aoqi@0 95
aoqi@0 96 @Test
aoqi@0 97 void localClassTest(RunKind rk, GenKind gk) throws Exception {
aoqi@0 98 List<File> files = new ArrayList<File>();
aoqi@0 99 files.add(createFile("p/C.java",
aoqi@0 100 "class C { native void m(); void m2() { class Local { } } }"));
aoqi@0 101
aoqi@0 102 Set<String> expect = createSet("C.h");
aoqi@0 103
aoqi@0 104 test(rk, gk, files, expect);
aoqi@0 105 }
aoqi@0 106
aoqi@0 107 @Test
aoqi@0 108 void syntheticClassTest(RunKind rk, GenKind gk) throws Exception {
aoqi@0 109 List<File> files = new ArrayList<File>();
aoqi@0 110 files.add(createFile("p/C.java",
aoqi@0 111 "class C {\n"
aoqi@0 112 + " private C() { }\n"
aoqi@0 113 + " class Inner extends C { native void m(); }\n"
aoqi@0 114 + "}"));
aoqi@0 115
aoqi@0 116 Set<String> expect = createSet("C_Inner.h");
aoqi@0 117 if (gk == GenKind.FULL) expect.add("C.h");
aoqi@0 118
aoqi@0 119 test(rk, gk, files, expect);
aoqi@0 120
aoqi@0 121 // double check the synthetic class was generated
aoqi@0 122 checkEqual("generatedClasses",
aoqi@0 123 createSet("C.class", "C$1.class", "C$Inner.class"),
aoqi@0 124 createSet(classesDir.list()));
aoqi@0 125 }
aoqi@0 126
aoqi@0 127 @Test
aoqi@0 128 void annoTest(RunKind rk, GenKind gk) throws Exception {
aoqi@0 129 List<File> files = new ArrayList<File>();
aoqi@0 130 files.add(createFile("p/C.java",
aoqi@0 131 "class C { @java.lang.annotation.Native public static final int i = 1907; }"));
aoqi@0 132
aoqi@0 133 Set<String> expect = createSet("C.h");
aoqi@0 134
aoqi@0 135 test(rk, gk, files, expect);
aoqi@0 136 }
aoqi@0 137
aoqi@0 138 @Test
aoqi@0 139 void annoNestedClassTest(RunKind rk, GenKind gk) throws Exception {
aoqi@0 140 List<File> files = new ArrayList<File>();
aoqi@0 141 files.add(createFile("p/C.java",
aoqi@0 142 "class C { class Inner { @java.lang.annotation.Native public static final int i = 1907; } }"));
aoqi@0 143
aoqi@0 144 Set<String> expect = createSet("C_Inner.h");
aoqi@0 145 if (gk == GenKind.FULL) expect.add("C.h");
aoqi@0 146
aoqi@0 147 test(rk, gk, files, expect);
aoqi@0 148 }
aoqi@0 149
aoqi@0 150 /**
aoqi@0 151 * The worker method for each test case.
aoqi@0 152 * Compile the files and verify that exactly the expected set of header files
aoqi@0 153 * is generated.
aoqi@0 154 */
aoqi@0 155 void test(RunKind rk, GenKind gk, List<File> files, Set<String> expect) throws Exception {
aoqi@0 156 List<String> args = new ArrayList<String>();
aoqi@0 157 if (gk == GenKind.FULL)
aoqi@0 158 args.add("-XDjavah:full");
aoqi@0 159
aoqi@0 160 switch (rk) {
aoqi@0 161 case CMD:
aoqi@0 162 args.add("-d");
aoqi@0 163 args.add(classesDir.getPath());
aoqi@0 164 args.add("-h");
aoqi@0 165 args.add(headersDir.getPath());
aoqi@0 166 for (File f: files)
aoqi@0 167 args.add(f.getPath());
aoqi@0 168 int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]));
aoqi@0 169 if (rc != 0)
aoqi@0 170 throw new Exception("compilation failed, rc=" + rc);
aoqi@0 171 break;
aoqi@0 172
aoqi@0 173 case API:
aoqi@0 174 fm.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(srcDir));
aoqi@0 175 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(classesDir));
aoqi@0 176 fm.setLocation(StandardLocation.NATIVE_HEADER_OUTPUT, Arrays.asList(headersDir));
aoqi@0 177 JavacTask task = javac.getTask(null, fm, null, args, null,
aoqi@0 178 fm.getJavaFileObjectsFromFiles(files));
aoqi@0 179 if (!task.call())
aoqi@0 180 throw new Exception("compilation failed");
aoqi@0 181 break;
aoqi@0 182 }
aoqi@0 183
aoqi@0 184 Set<String> found = createSet(headersDir.list());
aoqi@0 185 checkEqual("header files", expect, found);
aoqi@0 186 }
aoqi@0 187
aoqi@0 188 /** Marker annotation for test cases. */
aoqi@0 189 @Retention(RetentionPolicy.RUNTIME)
aoqi@0 190 @interface Test { }
aoqi@0 191
aoqi@0 192 /** Combo test to run all test cases in all modes. */
aoqi@0 193 void run() throws Exception {
aoqi@0 194 javac = JavacTool.create();
aoqi@0 195 fm = javac.getStandardFileManager(null, null, null);
aoqi@0 196
aoqi@0 197 for (RunKind rk: RunKind.values()) {
aoqi@0 198 for (GenKind gk: GenKind.values()) {
aoqi@0 199 for (Method m: getClass().getDeclaredMethods()) {
aoqi@0 200 Annotation a = m.getAnnotation(Test.class);
aoqi@0 201 if (a != null) {
aoqi@0 202 init(rk, gk, m.getName());
aoqi@0 203 try {
aoqi@0 204 m.invoke(this, new Object[] { rk, gk });
aoqi@0 205 } catch (InvocationTargetException e) {
aoqi@0 206 Throwable cause = e.getCause();
aoqi@0 207 throw (cause instanceof Exception) ? ((Exception) cause) : e;
aoqi@0 208 }
aoqi@0 209 System.err.println();
aoqi@0 210 }
aoqi@0 211 }
aoqi@0 212 }
aoqi@0 213 }
aoqi@0 214 System.err.println(testCount + " tests" + ((errorCount == 0) ? "" : ", " + errorCount + " errors"));
aoqi@0 215 if (errorCount > 0)
aoqi@0 216 throw new Exception(errorCount + " errors found");
aoqi@0 217 }
aoqi@0 218
aoqi@0 219 /**
aoqi@0 220 * Init directories for a test case.
aoqi@0 221 */
aoqi@0 222 void init(RunKind rk, GenKind gk, String name) throws IOException {
aoqi@0 223 System.err.println("Test " + rk + " " + gk + " " + name);
aoqi@0 224 testCount++;
aoqi@0 225
aoqi@0 226 testDir = new File(rk.toString().toLowerCase() + "_" + gk.toString().toLowerCase() + "-" + name);
aoqi@0 227 srcDir = new File(testDir, "src");
aoqi@0 228 srcDir.mkdirs();
aoqi@0 229 classesDir = new File(testDir, "classes");
aoqi@0 230 classesDir.mkdirs();
aoqi@0 231 headersDir = new File(testDir, "headers");
aoqi@0 232 headersDir.mkdirs();
aoqi@0 233 }
aoqi@0 234
aoqi@0 235 /** Create a source file with given body text. */
aoqi@0 236 File createFile(String path, final String body) throws IOException {
aoqi@0 237 File f = new File(srcDir, path);
aoqi@0 238 f.getParentFile().mkdirs();
aoqi@0 239 try (FileWriter out = new FileWriter(f)) {
aoqi@0 240 out.write(body);
aoqi@0 241 }
aoqi@0 242 return f;
aoqi@0 243 }
aoqi@0 244
aoqi@0 245 /** Convenience method to create a set of items. */
aoqi@0 246 <T> Set<T> createSet(T... items) {
aoqi@0 247 return new HashSet<T>(Arrays.asList(items));
aoqi@0 248 }
aoqi@0 249
aoqi@0 250 /** Convenience method to check two values are equal, and report an error if not. */
aoqi@0 251 <T> void checkEqual(String label, T expect, T found) {
aoqi@0 252 if ((found == null) ? (expect == null) : found.equals(expect))
aoqi@0 253 return;
aoqi@0 254 System.err.println("Error: mismatch");
aoqi@0 255 System.err.println(" expected: " + expect);
aoqi@0 256 System.err.println(" found: " + found);
aoqi@0 257 errorCount++;
aoqi@0 258 }
aoqi@0 259
aoqi@0 260 // Shared across API test cases
aoqi@0 261 JavacTool javac;
aoqi@0 262 StandardJavaFileManager fm;
aoqi@0 263
aoqi@0 264 // Directories set up by init
aoqi@0 265 File testDir;
aoqi@0 266 File srcDir;
aoqi@0 267 File classesDir;
aoqi@0 268 File headersDir;
aoqi@0 269
aoqi@0 270 // Statistics
aoqi@0 271 int testCount;
aoqi@0 272 int errorCount;
aoqi@0 273 }
aoqi@0 274

mercurial