test/tools/javac/nativeHeaders/NativeHeaderTest.java

Wed, 08 Oct 2014 14:16:40 -0700

author
asaha
date
Wed, 08 Oct 2014 14:16:40 -0700
changeset 2586
f5e5ca7505e2
parent 1723
a2889739cf21
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Merge

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

mercurial