test/tools/javac/nativeHeaders/NativeHeaderTest.java

Thu, 21 Feb 2013 15:26:46 +0000

author
mcimadamore
date
Thu, 21 Feb 2013 15:26:46 +0000
changeset 1599
9f0ec00514b6
parent 1407
f14c693a0e48
child 1723
a2889739cf21
permissions
-rw-r--r--

8007461: Regression: bad overload resolution when inner class and outer class have method with same name
Summary: Fix regression in varargs method resolution introduced by bad refactoring
Reviewed-by: jjg

jjg@1230 1 /*
jjg@1230 2 * Copyright (c) 2012, 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@1407 26 * @bug 7150368 8003412
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 oldAnnoTest(RunKind rk, GenKind gk) throws Exception {
jjg@1230 129 List<File> files = new ArrayList<File>();
jjg@1230 130 files.add(createFile("p/C.java",
jjg@1230 131 "@javax.tools.annotation.GenerateNativeHeader class C { }"));
jjg@1230 132
jjg@1230 133 Set<String> expect = createSet("C.h");
jjg@1230 134
jjg@1230 135 test(rk, gk, files, expect);
jjg@1230 136 }
jjg@1230 137
jjg@1230 138 @Test
jjg@1407 139 void annoTest(RunKind rk, GenKind gk) throws Exception {
jjg@1407 140 List<File> files = new ArrayList<File>();
jjg@1407 141 files.add(createFile("p/C.java",
jjg@1407 142 "class C { @java.lang.annotation.Native public static final int i = 1907; }"));
jjg@1407 143
jjg@1407 144 Set<String> expect = createSet("C.h");
jjg@1407 145
jjg@1407 146 test(rk, gk, files, expect);
jjg@1407 147 }
jjg@1407 148
jjg@1407 149 @Test
jjg@1407 150 void oldAnnoNestedClassTest(RunKind rk, GenKind gk) throws Exception {
jjg@1407 151 List<File> files = new ArrayList<File>();
jjg@1407 152 files.add(createFile("p/C.java",
jjg@1407 153 "class C { @javax.tools.annotation.GenerateNativeHeader class Inner { } }"));
jjg@1407 154
jjg@1407 155 Set<String> expect = createSet("C_Inner.h");
jjg@1407 156 if (gk == GenKind.FULL) expect.add("C.h");
jjg@1407 157
jjg@1407 158 test(rk, gk, files, expect);
jjg@1407 159 }
jjg@1407 160
jjg@1407 161 @Test
jjg@1230 162 void annoNestedClassTest(RunKind rk, GenKind gk) throws Exception {
jjg@1230 163 List<File> files = new ArrayList<File>();
jjg@1230 164 files.add(createFile("p/C.java",
jjg@1407 165 "class C { class Inner { @java.lang.annotation.Native public static final int i = 1907; } }"));
jjg@1230 166
jjg@1230 167 Set<String> expect = createSet("C_Inner.h");
jjg@1230 168 if (gk == GenKind.FULL) expect.add("C.h");
jjg@1230 169
jjg@1230 170 test(rk, gk, files, expect);
jjg@1230 171 }
jjg@1230 172
jjg@1230 173 /**
jjg@1230 174 * The worker method for each test case.
jjg@1230 175 * Compile the files and verify that exactly the expected set of header files
jjg@1230 176 * is generated.
jjg@1230 177 */
jjg@1230 178 void test(RunKind rk, GenKind gk, List<File> files, Set<String> expect) throws Exception {
jjg@1230 179 List<String> args = new ArrayList<String>();
jjg@1230 180 if (gk == GenKind.FULL)
jjg@1230 181 args.add("-XDjavah:full");
jjg@1230 182
jjg@1230 183 switch (rk) {
jjg@1230 184 case CMD:
jjg@1230 185 args.add("-d");
jjg@1230 186 args.add(classesDir.getPath());
jjg@1230 187 args.add("-h");
jjg@1230 188 args.add(headersDir.getPath());
jjg@1230 189 for (File f: files)
jjg@1230 190 args.add(f.getPath());
jjg@1230 191 int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]));
jjg@1230 192 if (rc != 0)
jjg@1230 193 throw new Exception("compilation failed, rc=" + rc);
jjg@1230 194 break;
jjg@1230 195
jjg@1230 196 case API:
jjg@1230 197 fm.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(srcDir));
jjg@1230 198 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(classesDir));
jjg@1230 199 fm.setLocation(StandardLocation.NATIVE_HEADER_OUTPUT, Arrays.asList(headersDir));
jjg@1230 200 JavacTask task = javac.getTask(null, fm, null, args, null,
jjg@1230 201 fm.getJavaFileObjectsFromFiles(files));
jjg@1230 202 if (!task.call())
jjg@1230 203 throw new Exception("compilation failed");
jjg@1230 204 break;
jjg@1230 205 }
jjg@1230 206
jjg@1230 207 Set<String> found = createSet(headersDir.list());
jjg@1230 208 checkEqual("header files", expect, found);
jjg@1230 209 }
jjg@1230 210
jjg@1230 211 /** Marker annotation for test cases. */
jjg@1230 212 @Retention(RetentionPolicy.RUNTIME)
jjg@1230 213 @interface Test { }
jjg@1230 214
jjg@1230 215 /** Combo test to run all test cases in all modes. */
jjg@1230 216 void run() throws Exception {
jjg@1230 217 javac = JavacTool.create();
jjg@1230 218 fm = javac.getStandardFileManager(null, null, null);
jjg@1230 219
jjg@1230 220 for (RunKind rk: RunKind.values()) {
jjg@1230 221 for (GenKind gk: GenKind.values()) {
jjg@1230 222 for (Method m: getClass().getDeclaredMethods()) {
jjg@1230 223 Annotation a = m.getAnnotation(Test.class);
jjg@1230 224 if (a != null) {
jjg@1230 225 init(rk, gk, m.getName());
jjg@1230 226 try {
jjg@1230 227 m.invoke(this, new Object[] { rk, gk });
jjg@1230 228 } catch (InvocationTargetException e) {
jjg@1230 229 Throwable cause = e.getCause();
jjg@1230 230 throw (cause instanceof Exception) ? ((Exception) cause) : e;
jjg@1230 231 }
jjg@1230 232 System.err.println();
jjg@1230 233 }
jjg@1230 234 }
jjg@1230 235 }
jjg@1230 236 }
jjg@1230 237 System.err.println(testCount + " tests" + ((errorCount == 0) ? "" : ", " + errorCount + " errors"));
jjg@1230 238 if (errorCount > 0)
jjg@1230 239 throw new Exception(errorCount + " errors found");
jjg@1230 240 }
jjg@1230 241
jjg@1230 242 /**
jjg@1230 243 * Init directories for a test case.
jjg@1230 244 */
jjg@1230 245 void init(RunKind rk, GenKind gk, String name) throws IOException {
jjg@1230 246 System.err.println("Test " + rk + " " + gk + " " + name);
jjg@1230 247 testCount++;
jjg@1230 248
jjg@1230 249 testDir = new File(rk.toString().toLowerCase() + "_" + gk.toString().toLowerCase() + "-" + name);
jjg@1230 250 srcDir = new File(testDir, "src");
jjg@1230 251 srcDir.mkdirs();
jjg@1230 252 classesDir = new File(testDir, "classes");
jjg@1230 253 classesDir.mkdirs();
jjg@1230 254 headersDir = new File(testDir, "headers");
jjg@1230 255 headersDir.mkdirs();
jjg@1230 256 }
jjg@1230 257
jjg@1230 258 /** Create a source file with given body text. */
jjg@1230 259 File createFile(String path, final String body) throws IOException {
jjg@1230 260 File f = new File(srcDir, path);
jjg@1230 261 f.getParentFile().mkdirs();
jjg@1230 262 try (FileWriter out = new FileWriter(f)) {
jjg@1230 263 out.write(body);
jjg@1230 264 }
jjg@1230 265 return f;
jjg@1230 266 }
jjg@1230 267
jjg@1230 268 /** Convenience method to create a set of items. */
jjg@1230 269 <T> Set<T> createSet(T... items) {
jjg@1230 270 return new HashSet<T>(Arrays.asList(items));
jjg@1230 271 }
jjg@1230 272
jjg@1230 273 /** Convenience method to check two values are equal, and report an error if not. */
jjg@1230 274 <T> void checkEqual(String label, T expect, T found) {
jjg@1230 275 if ((found == null) ? (expect == null) : found.equals(expect))
jjg@1230 276 return;
jjg@1230 277 System.err.println("Error: mismatch");
jjg@1230 278 System.err.println(" expected: " + expect);
jjg@1230 279 System.err.println(" found: " + found);
jjg@1230 280 errorCount++;
jjg@1230 281 }
jjg@1230 282
jjg@1230 283 // Shared across API test cases
jjg@1230 284 JavacTool javac;
jjg@1230 285 StandardJavaFileManager fm;
jjg@1230 286
jjg@1230 287 // Directories set up by init
jjg@1230 288 File testDir;
jjg@1230 289 File srcDir;
jjg@1230 290 File classesDir;
jjg@1230 291 File headersDir;
jjg@1230 292
jjg@1230 293 // Statistics
jjg@1230 294 int testCount;
jjg@1230 295 int errorCount;
jjg@1230 296 }
jjg@1230 297

mercurial