8015372: Update tests for Method Parameter Reflection API to check whether a parameter is final

Reviewed-by: jjg, jfranck
This commit is contained in:
Matherey Nunez 2013-10-17 13:27:36 +02:00
parent b8aff04aa0
commit 7c6e4696ab
23 changed files with 352 additions and 51 deletions

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters AnnotationTest.java * @compile -parameters AnnotationTest.java
* @run main Tester AnnotationTest * @run main Tester AnnotationTest AnnotationTest.out
*/ */
import java.lang.annotation.*; import java.lang.annotation.*;

View file

@ -0,0 +1,10 @@
static interface AnnotationTest$Annos -- inner
AnnotationTest$Annos.foo()
AnnotationTest$Annos.value()
class AnnotationTest --
AnnotationTest.<init>(i, ji)
AnnotationTest.foo(i, ji)
static interface AnnotationTest$I -- inner
AnnotationTest$I.m(i, ji)
static interface AnnotationTest$Anno -- inner
AnnotationTest$Anno.f()

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters AnonymousClass.java * @compile -parameters AnonymousClass.java
* @run main Tester AnonymousClass * @run main Tester AnonymousClass AnonymousClass.out
*/ */
class AnonymousClass { class AnonymousClass {

View file

@ -0,0 +1,80 @@
static public class AnonymousClass$Sinner -- inner
AnonymousClass$Sinner.<init>()
AnonymousClass$Sinner.<init>(arg, barg)
AnonymousClass$Sinner.m(s/*synthetic*/, ts/*synthetic*/)/*synthetic*/
AnonymousClass$Sinner.m()/*synthetic*/
AnonymousClass$Sinner.m(s, ts)
AnonymousClass$Sinner.m()
class AnonymousClass$9 -- anon
AnonymousClass$9.<init>(final this$0/*implicit*/)
AnonymousClass$9.m()/*synthetic*/
AnonymousClass$9.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$9.m(i, ji)
AnonymousClass$9.m()
class AnonymousClass$Inner -- inner
AnonymousClass$Inner.<init>(final this$0/*synthetic*/)
AnonymousClass$Inner.<init>(final this$0/*synthetic*/, arg, barg)
AnonymousClass$Inner.m(s/*synthetic*/, ts/*synthetic*/)/*synthetic*/
AnonymousClass$Inner.m()/*synthetic*/
AnonymousClass$Inner.m(s, ts)
AnonymousClass$Inner.m()
class AnonymousClass$3 -- anon
AnonymousClass$3.<init>(final this$0/*implicit*/, arg, barg)
AnonymousClass$3.m()/*synthetic*/
AnonymousClass$3.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$3.m(i, ji)
AnonymousClass$3.m()
class AnonymousClass$2 -- anon
AnonymousClass$2.<init>(final this$0/*implicit*/)
AnonymousClass$2.m()/*synthetic*/
AnonymousClass$2.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$2.m(i, ji)
AnonymousClass$2.m()
class AnonymousClass --
AnonymousClass.<init>(final a, ba)
AnonymousClass.foo(final a, ba)
class AnonymousClass$5 -- anon
AnonymousClass$5.<init>(final this$0/*implicit*/, arg, barg)
AnonymousClass$5.m()/*synthetic*/
AnonymousClass$5.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$5.m(i, ji)
AnonymousClass$5.m()
static interface AnonymousClass$I -- inner
AnonymousClass$I.m()
AnonymousClass$I.m(x, yx)
class AnonymousClass$10 -- anon
AnonymousClass$10.<init>(final this$0/*implicit*/, arg, barg)
AnonymousClass$10.m()/*synthetic*/
AnonymousClass$10.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$10.m(i, ji)
AnonymousClass$10.m()
class AnonymousClass$8 -- anon
AnonymousClass$8.<init>(final this$0/*implicit*/, arg, barg)
AnonymousClass$8.m()/*synthetic*/
AnonymousClass$8.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$8.m(i, ji)
AnonymousClass$8.m()
class AnonymousClass$6 -- anon
AnonymousClass$6.<init>(final this$0/*implicit*/)
AnonymousClass$6.m()/*synthetic*/
AnonymousClass$6.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$6.m(i, ji)
AnonymousClass$6.m()
class AnonymousClass$7 -- anon
AnonymousClass$7.<init>(final this$0/*implicit*/)
AnonymousClass$7.m()/*synthetic*/
AnonymousClass$7.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$7.m(i, ji)
AnonymousClass$7.m()
class AnonymousClass$4 -- anon
AnonymousClass$4.<init>(final this$0/*implicit*/)
AnonymousClass$4.m()/*synthetic*/
AnonymousClass$4.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$4.m(i, ji)
AnonymousClass$4.m()
class AnonymousClass$1 -- anon
AnonymousClass$1.<init>(final this$0/*implicit*/)
AnonymousClass$1.m()/*synthetic*/
AnonymousClass$1.m(i/*synthetic*/, ji/*synthetic*/)/*synthetic*/
AnonymousClass$1.m(i, ji)
AnonymousClass$1.m()

View file

@ -82,15 +82,14 @@ class ClassFileVisitor extends Tester.Visitor {
* Read the class and determine some key characteristics, like if it's * Read the class and determine some key characteristics, like if it's
* an enum, or inner class, etc. * an enum, or inner class, etc.
*/ */
void visitClass(final String cname, final File cfile, final StringBuilder sb) void visitClass(final String cname, final File cfile, final StringBuilder sb) throws Exception {
throws Exception {
this.cname = cname; this.cname = cname;
classFile = ClassFile.read(cfile); classFile = ClassFile.read(cfile);
isEnum = classFile.access_flags.is(AccessFlags.ACC_ENUM); isEnum = classFile.access_flags.is(AccessFlags.ACC_ENUM);
isInterface = classFile.access_flags.is(AccessFlags.ACC_INTERFACE); isInterface = classFile.access_flags.is(AccessFlags.ACC_INTERFACE);
isPublic = classFile.access_flags.is(AccessFlags.ACC_PUBLIC); isPublic = classFile.access_flags.is(AccessFlags.ACC_PUBLIC);
isInner = false; isInner = false;
isStatic = true; isStatic = false;
isAnon = false; isAnon = false;
Attribute attr = classFile.getAttribute("InnerClasses"); Attribute attr = classFile.getAttribute("InnerClasses");
@ -100,10 +99,11 @@ class ClassFileVisitor extends Tester.Visitor {
sb.append(isStatic ? "static " : "") sb.append(isStatic ? "static " : "")
.append(isPublic ? "public " : "") .append(isPublic ? "public " : "")
.append(isEnum ? "enum " : isInterface ? "interface " : "class ") .append(isEnum ? "enum " : isInterface ? "interface " : "class ")
.append(cname).append(" -- ") .append(cname).append(" -- ");
.append(isInner? "inner " : "" ) if (isInner) {
.append(isAnon ? "anon" : "") sb.append(isAnon ? "anon" : "inner");
.append("\n");; }
sb.append("\n");
for (Method method : classFile.methods) { for (Method method : classFile.methods) {
new MethodVisitor().visitMethod(method, sb); new MethodVisitor().visitMethod(method, sb);
@ -148,7 +148,9 @@ class ClassFileVisitor extends Tester.Visitor {
public int mNumParams; public int mNumParams;
public boolean mSynthetic; public boolean mSynthetic;
public boolean mIsConstructor; public boolean mIsConstructor;
public boolean mIsClinit;
public boolean mIsBridge; public boolean mIsBridge;
public boolean isFinal;
public String prefix; public String prefix;
void visitMethod(Method method, StringBuilder sb) throws Exception { void visitMethod(Method method, StringBuilder sb) throws Exception {
@ -160,9 +162,13 @@ class ClassFileVisitor extends Tester.Visitor {
mNumParams = -1; // no MethodParameters attribute found mNumParams = -1; // no MethodParameters attribute found
mSynthetic = method.access_flags.is(AccessFlags.ACC_SYNTHETIC); mSynthetic = method.access_flags.is(AccessFlags.ACC_SYNTHETIC);
mIsConstructor = mName.equals("<init>"); mIsConstructor = mName.equals("<init>");
mIsClinit = mName.equals("<clinit>");
prefix = cname + "." + mName + "() - "; prefix = cname + "." + mName + "() - ";
mIsBridge = method.access_flags.is(AccessFlags.ACC_BRIDGE); mIsBridge = method.access_flags.is(AccessFlags.ACC_BRIDGE);
if (mIsClinit) {
sb = new StringBuilder(); // Discard output
}
sb.append(cname).append(".").append(mName).append("("); sb.append(cname).append(".").append(mName).append("(");
for (Attribute a : method.attributes) { for (Attribute a : method.attributes) {
@ -170,9 +176,18 @@ class ClassFileVisitor extends Tester.Visitor {
} }
if (mNumParams == -1) { if (mNumParams == -1) {
if (mSynthetic) { if (mSynthetic) {
sb.append("<none>)!!"); // We don't generate MethodParameters attribute for synthetic
// methods, so we are creating a parameter pattern to match
// ReflectionVisitor API output.
for (int i = 0; i < mParams; i++) {
if (i == 0)
sb.append("arg").append(i);
else
sb.append(", arg").append(i);
}
sb.append(")/*synthetic*/");
} else { } else {
sb.append("<none>)"); sb.append(")");
} }
} }
sb.append("\n"); sb.append("\n");
@ -217,7 +232,7 @@ class ClassFileVisitor extends Tester.Visitor {
String sep = ""; String sep = "";
String userParam = null; String userParam = null;
for (int x = 0; x < mNumParams; x++) { for (int x = 0; x < mNumParams; x++) {
isFinal = (mp.method_parameter_table[x].flags & AccessFlags.ACC_FINAL) != 0;
// IMPL: Assume all parameters are named, something. // IMPL: Assume all parameters are named, something.
int cpi = mp.method_parameter_table[x].name_index; int cpi = mp.method_parameter_table[x].name_index;
if (cpi == 0) { if (cpi == 0) {
@ -229,6 +244,8 @@ class ClassFileVisitor extends Tester.Visitor {
String param = null; String param = null;
try { try {
param = classFile.constant_pool.getUTF8Value(cpi); param = classFile.constant_pool.getUTF8Value(cpi);
if (isFinal)
param = "final " + param;
sb.append(sep).append(param); sb.append(sep).append(param);
sep = ", "; sep = ", ";
} catch(ConstantPoolException e) { } catch(ConstantPoolException e) {
@ -239,7 +256,7 @@ class ClassFileVisitor extends Tester.Visitor {
// Check availability, flags and special names // Check availability, flags and special names
int check = checkParam(mp, param, x, sb); int check = checkParam(mp, param, x, sb, isFinal);
if (check < 0) { if (check < 0) {
return null; return null;
} }
@ -253,9 +270,15 @@ class ClassFileVisitor extends Tester.Visitor {
char c = userParam.charAt(0); char c = userParam.charAt(0);
expect = (++c) + userParam; expect = (++c) + userParam;
} }
if(isFinal && expect != null)
expect = "final " + expect;
if (check > 0) { if (check > 0) {
if(isFinal) {
userParam = param.substring(6);
} else {
userParam = param; userParam = param;
} }
}
if (expect != null && !param.equals(expect)) { if (expect != null && !param.equals(expect)) {
error(prefix + "param[" + x + "]='" error(prefix + "param[" + x + "]='"
+ param + "' expected '" + expect + "'"); + param + "' expected '" + expect + "'");
@ -263,7 +286,7 @@ class ClassFileVisitor extends Tester.Visitor {
} }
} }
if (mSynthetic) { if (mSynthetic) {
sb.append(")!!"); sb.append(")/*synthetic*/");
} else { } else {
sb.append(")"); sb.append(")");
} }
@ -278,7 +301,7 @@ class ClassFileVisitor extends Tester.Visitor {
* explicitly declared parameter. * explicitly declared parameter.
*/ */
int checkParam(MethodParameters_attribute mp, String param, int index, int checkParam(MethodParameters_attribute mp, String param, int index,
StringBuilder sb) { StringBuilder sb, boolean isFinal) {
boolean synthetic = (mp.method_parameter_table[index].flags boolean synthetic = (mp.method_parameter_table[index].flags
& AccessFlags.ACC_SYNTHETIC) != 0; & AccessFlags.ACC_SYNTHETIC) != 0;
@ -304,9 +327,13 @@ class ClassFileVisitor extends Tester.Visitor {
} }
} else if (index == 0) { } else if (index == 0) {
if (isAnon) { if (isAnon) {
expect = "this\\$[0-9]+";
allowMandated = true; allowMandated = true;
expect = "this\\$[0-n]*"; if (isFinal) {
expect = "final this\\$[0-9]+";
}
} else if (isInner && !isStatic) { } else if (isInner && !isStatic) {
expect = "this\\$[0-9]+";
allowMandated = true; allowMandated = true;
if (!isPublic) { if (!isPublic) {
// some but not all non-public inner classes // some but not all non-public inner classes
@ -314,7 +341,9 @@ class ClassFileVisitor extends Tester.Visitor {
// the test a bit of slack and allow either. // the test a bit of slack and allow either.
allowSynthetic = true; allowSynthetic = true;
} }
expect = "this\\$[0-n]*"; if (isFinal) {
expect = "final this\\$[0-9]+";
}
} }
} }
} else if (isEnum && mNumParams == 1 && index == 0 && mName.equals("valueOf")) { } else if (isEnum && mNumParams == 1 && index == 0 && mName.equals("valueOf")) {
@ -327,8 +356,8 @@ class ClassFileVisitor extends Tester.Visitor {
*/ */
expect = null; expect = null;
} }
if (mandated) sb.append("!"); if (mandated) sb.append("/*implicit*/");
if (synthetic) sb.append("!!"); if (synthetic) sb.append("/*synthetic*/");
// IMPL: our rules a somewhat fuzzy, sometimes allowing both mandated // IMPL: our rules a somewhat fuzzy, sometimes allowing both mandated
// and synthetic. However, a parameters cannot be both. // and synthetic. However, a parameters cannot be both.

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters Constructors.java * @compile -parameters Constructors.java
* @run main Tester Constructors * @run main Tester Constructors Constructors.out
*/ */
public class Constructors { public class Constructors {

View file

@ -0,0 +1,5 @@
public class Constructors --
Constructors.<init>()
Constructors.<init>(final a, final ba)
Constructors.<init>(a, final ba, final cba)
Constructors.<init>(a, ba, final cba, final dcba)

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters EnumTest.java * @compile -parameters EnumTest.java
* @run main Tester EnumTest * @run main Tester EnumTest EnumTest.out
*/ */
/** Test that parameter names are recorded for enum methods */ /** Test that parameter names are recorded for enum methods */

View file

@ -0,0 +1,7 @@
enum EnumTest --
EnumTest.<init>($enum$name/*synthetic*/, $enum$ordinal/*synthetic*/)
EnumTest.<init>($enum$name/*synthetic*/, $enum$ordinal/*synthetic*/, a, ba)
EnumTest.ok(c, dc)
EnumTest.values()
EnumTest.valueOf(A, BA)
EnumTest.valueOf(name/*implicit*/)

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters InstanceMethods.java * @compile -parameters InstanceMethods.java
* @run main Tester InstanceMethods * @run main Tester InstanceMethods InstanceMethods.out
*/ */
public class InstanceMethods { public class InstanceMethods {

View file

@ -0,0 +1,11 @@
public class InstanceMethods --
InstanceMethods.<init>()
InstanceMethods.empty()
InstanceMethods.def(a, final ba, final cba)
InstanceMethods.pub(d, final ed, final fed)
InstanceMethods.prot(g, final hg, final ihg)
InstanceMethods.priv(j, final kj, final lkj)
InstanceMethods.def(A, BA, final CBA, final DCBA)
InstanceMethods.pub(B, CB, final DCB, final EDCB)
InstanceMethods.prot(C, DC, final EDC, final FEDC)
InstanceMethods.priv(D, ED, final FED, final GFED)

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters LambdaTest.java * @compile -parameters LambdaTest.java
* @run main Tester LambdaTest * @run main Tester LambdaTest LambdaTest.out
*/ */
/** /**

View file

@ -0,0 +1,7 @@
class LambdaTest --
LambdaTest.<init>()
LambdaTest.foo(i)
LambdaTest.lambda$1(arg0, arg1)/*synthetic*/
LambdaTest.lambda$0(arg0)/*synthetic*/
static interface LambdaTest$I -- inner
LambdaTest$I.m(x)

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters LocalClassTest.java * @compile -parameters LocalClassTest.java
* @run main Tester LocalClassTest * @run main Tester LocalClassTest LocalClassTest.out
*/ */
class LocalClassTest { class LocalClassTest {

View file

@ -0,0 +1,12 @@
class LocalClassTest$1Local_has_constructor -- inner
LocalClassTest$1Local_has_constructor.<init>(final this$0/*implicit*/, a, ba)
LocalClassTest$1Local_has_constructor.<init>(final this$0/*implicit*/)
LocalClassTest$1Local_has_constructor.foo(m, nm)
LocalClassTest$1Local_has_constructor.foo()
class LocalClassTest$1Local_default_constructor -- inner
LocalClassTest$1Local_default_constructor.<init>(final this$0/*implicit*/)
LocalClassTest$1Local_default_constructor.foo()
LocalClassTest$1Local_default_constructor.foo(m, nm)
class LocalClassTest --
LocalClassTest.<init>()
LocalClassTest.foo()

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters MemberClassTest.java * @compile -parameters MemberClassTest.java
* @run main Tester MemberClassTest * @run main Tester MemberClassTest MemberClassTest.out
*/ */
class MemberClassTest { class MemberClassTest {

View file

@ -0,0 +1,33 @@
static class MemberClassTest$Static_Member -- inner
MemberClassTest$Static_Member.<init>()
MemberClassTest$Static_Member.<init>(arg, barg)
MemberClassTest$Static_Member.m(s, ts)
MemberClassTest$Static_Member.m()
public class MemberClassTest$Member -- inner
MemberClassTest$Member.<init>(final this$0/*implicit*/)
MemberClassTest$Member.<init>(final this$0/*implicit*/, a, ba)
MemberClassTest$Member.m(s, ts)
MemberClassTest$Member.m()
public class MemberClassTest$Member$Member_Member -- inner
MemberClassTest$Member$Member_Member.<init>(final this$1/*implicit*/)
MemberClassTest$Member$Member_Member.<init>(final this$1/*implicit*/, x, yx)
class MemberClassTest$1 -- anon
MemberClassTest$1.<init>(final this$0/*implicit*/)
MemberClassTest$1.m()
MemberClassTest$1.m(s, ts)
static public class MemberClassTest$Static_Member$Static_Member_Static_Member -- inner
MemberClassTest$Static_Member$Static_Member_Static_Member.<init>()
MemberClassTest$Static_Member$Static_Member_Static_Member.<init>(x, yx)
public class MemberClassTest$Static_Member$Static_Member_Member -- inner
MemberClassTest$Static_Member$Static_Member_Member.<init>(final this$0/*implicit*/)
MemberClassTest$Static_Member$Static_Member_Member.<init>(final this$0/*implicit*/, x, yx)
class MemberClassTest --
MemberClassTest.<init>(final a, ba)
MemberClassTest.<init>()
MemberClassTest.foo()
static interface MemberClassTest$I -- inner
MemberClassTest$I.m()
MemberClassTest$I.m(x, yx)
class MemberClassTest$1$Anonymous_Member -- inner
MemberClassTest$1$Anonymous_Member.<init>(final this$1/*implicit*/)
MemberClassTest$1$Anonymous_Member.<init>(final this$1/*implicit*/, x, yx)

View file

@ -48,6 +48,7 @@ public class ReflectionVisitor extends Tester.Visitor {
boolean isMember; boolean isMember;
boolean isStatic; boolean isStatic;
boolean isPublic; boolean isPublic;
boolean isFinal;
Class clazz; Class clazz;
StringBuilder sb; StringBuilder sb;
@ -72,8 +73,8 @@ public class ReflectionVisitor extends Tester.Visitor {
.append(isPublic ? "public " : "") .append(isPublic ? "public " : "")
.append(isEnum ? "enum " : isInterface ? "interface " : "class ") .append(isEnum ? "enum " : isInterface ? "interface " : "class ")
.append(cl).append(" -- ") .append(cl).append(" -- ")
.append(isMember? "member " : "" ) .append(isMember? "inner" : "" )
.append(isLocal? "local " : "" ) .append(isLocal? "inner" : "" )
.append(isAnon ? "anon" : "") .append(isAnon ? "anon" : "")
.append("\n"); .append("\n");
@ -82,7 +83,6 @@ public class ReflectionVisitor extends Tester.Visitor {
} }
for (Method m :clazz.getDeclaredMethods()) { for (Method m :clazz.getDeclaredMethods()) {
testMethod(m); testMethod(m);
} }
} }
@ -116,9 +116,15 @@ public class ReflectionVisitor extends Tester.Visitor {
for (Parameter p : c.getParameters()) { for (Parameter p : c.getParameters()) {
i++; i++;
String pname = p.getName(); String pname = p.getName();
int pmodifier = p.getModifiers();
isFinal = false;
if (Modifier.isFinal(pmodifier)) {
isFinal = true;
pname = "final " + pname;
}
sb.append(sep).append(pname); sb.append(sep).append(pname);
if (p.isImplicit()) sb.append("!"); if (p.isImplicit()) sb.append("/*implicit*/");
if (p.isSynthetic()) sb.append("!!"); if (p.isSynthetic()) sb.append("/*synthetic*/");
sep = ", "; sep = ", ";
// Set expectations // Set expectations
@ -135,11 +141,17 @@ public class ReflectionVisitor extends Tester.Visitor {
} }
} else if (i == 0) { } else if (i == 0) {
if (isAnon) { if (isAnon) {
expect = "this\\$[0-9]+";
allowImplicit = true; allowImplicit = true;
if (isFinal)
expect = "final this\\$[0-9]+";
} else if (isLocal) { } else if (isLocal) {
expect = "this\\$[0-9]+";
allowImplicit = true; allowImplicit = true;
expect = "this\\$[0-n]*"; if (isFinal)
expect = "final this\\$[0-9]+";
} else if ((isMember && !isStatic)) { } else if ((isMember && !isStatic)) {
expect = "this\\$[0-9]+";
allowImplicit = true; allowImplicit = true;
if (!isPublic) { if (!isPublic) {
// some but not all non-public inner classes // some but not all non-public inner classes
@ -147,7 +159,8 @@ public class ReflectionVisitor extends Tester.Visitor {
// the test a bit of slack and allow either. // the test a bit of slack and allow either.
allowSynthetic = true; allowSynthetic = true;
} }
expect = "this\\$[0-n]*"; if (isFinal)
expect = "final this\\$[0-9]+";
} }
} }
@ -201,11 +214,16 @@ public class ReflectionVisitor extends Tester.Visitor {
char ch = param.charAt(0); char ch = param.charAt(0);
expect = (++ch) + param; expect = (++ch) + param;
} }
if (isFinal && expect != null) {
expect = "final " + expect;
}
if (pname != null && fidelity) { if (pname != null && fidelity) {
if (isFinal) {
param = pname.substring(6);
} else {
param = pname; param = pname;
} }
}
if (expect != null && !expect.equals(pname)) { if (expect != null && !expect.equals(pname)) {
error(prefix + "param[" + i + "]='" + pname + error(prefix + "param[" + i + "]='" + pname +
"' expected '" + expect + "'"); "' expected '" + expect + "'");
@ -213,7 +231,7 @@ public class ReflectionVisitor extends Tester.Visitor {
} }
} }
if (c.isSynthetic()) { if (c.isSynthetic()) {
sb.append(")!!\n"); sb.append(")/*synthetic*/\n");
} else { } else {
sb.append(")\n"); sb.append(")\n");
} }
@ -240,13 +258,24 @@ public class ReflectionVisitor extends Tester.Visitor {
// the test-case design pattern, except synthetic methods. // the test-case design pattern, except synthetic methods.
for (Parameter p : m.getParameters()) { for (Parameter p : m.getParameters()) {
i++; i++;
isFinal = false;
int pmodifier = p.getModifiers();
if (param == null) { if (param == null) {
param = p.getName(); param = p.getName();
if (Modifier.isFinal(pmodifier)) {
isFinal = true;
param = "final " + param;
}
sb.append(sep).append(param); sb.append(sep).append(param);
} else { } else {
char c = param.charAt(0); char c = param.charAt(0);
String expect = m.isSynthetic() ? ("arg" + i) : ((++c) + param); String expect = m.isSynthetic() ? ("arg" + i) : ((++c) + param);
param = p.getName(); param = p.getName();
if (Modifier.isFinal(pmodifier)) {
isFinal = true;
expect = "final " + expect;
param = "final " + param;
}
sb.append(sep).append(param); sb.append(sep).append(param);
if (!m.isBridge() && !expect.equals(param)) { if (!m.isBridge() && !expect.equals(param)) {
error(prefix + "param[" + i + "]='" error(prefix + "param[" + i + "]='"
@ -254,10 +283,18 @@ public class ReflectionVisitor extends Tester.Visitor {
break; break;
} }
} }
if(isFinal)
param = param.substring(6);
if (p.isImplicit()) {
sb.append("/*implicit*/");
}
if (p.isSynthetic()) {
sb.append("/*synthetic*/");
}
sep = ", "; sep = ", ";
} }
if (m.isSynthetic()) { if (m.isSynthetic()) {
sb.append(")!!\n"); sb.append(")/*synthetic*/\n");
} else { } else {
sb.append(")\n"); sb.append(")\n");
} }

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters StaticMethods.java * @compile -parameters StaticMethods.java
* @run main Tester StaticMethods * @run main Tester StaticMethods StaticMethods.out
*/ */
public class StaticMethods { public class StaticMethods {

View file

@ -0,0 +1,11 @@
public class StaticMethods --
StaticMethods.<init>()
StaticMethods.def(a, ba, final cba, final dcba)
StaticMethods.def(a, final ba, final cba)
StaticMethods.pub(d, final ed, final fed)
StaticMethods.pub(a, ba, final cba, final dcba)
StaticMethods.prot(g, final hg, final ihg)
StaticMethods.prot(aa, baa, final cbaa, final dcbaa)
StaticMethods.priv(j, final kj, final lkj)
StaticMethods.priv(abc, babc, final cbabc, final dcbabc)
StaticMethods.empty()

View file

@ -23,6 +23,12 @@
import java.io.*; import java.io.*;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/** /**
* Test driver for MethodParameters testing. * Test driver for MethodParameters testing.
@ -44,6 +50,13 @@ public class Tester {
final static File classesdir = new File(System.getProperty("test.classes", ".")); final static File classesdir = new File(System.getProperty("test.classes", "."));
private String classname;
private File[] files;
private File refFile;
private int errors;
private int warnings;
private int diffGolden;
/** /**
* The visitor classes that does the actual checking are referenced * The visitor classes that does the actual checking are referenced
* statically, to force compilations, without having to reference * statically, to force compilations, without having to reference
@ -62,32 +75,38 @@ public class Tester {
* Test-driver expect a single classname as argument. * Test-driver expect a single classname as argument.
*/ */
public static void main(String... args) throws Exception { public static void main(String... args) throws Exception {
if (args.length != 1) { if (args.length != 2) {
throw new Error("A single class name is expected as argument"); throw new Error("A single class name and a golden file are expected as argument");
} }
final String pattern = args[0] + ".*\\.class"; String testSrc = System.getProperty("test.src");
File files[] = classesdir.listFiles(new FileFilter() { String testName = args[0];
String testGoldenFile = args[1];
final String pattern = testName + ".*\\.class";
File refFile = new File(testSrc, testGoldenFile);
File[] files = classesdir.listFiles(new FileFilter() {
public boolean accept(File f) { public boolean accept(File f) {
return f.getName().matches(pattern); return f.getName().matches(pattern);
} }
}); });
if (files.length == 0) { if (files.length == 0) {
File file = new File(classesdir, args[0] + ".class"); File file = new File(classesdir, testName + ".class");
throw new Error(file.getPath() + " not found"); throw new Error(file.getPath() + " not found");
} }
new Tester(args[0], files).run(); new Tester(testName, files, refFile).run();
} }
public Tester(String name, File files[]) { public Tester(String name, File[] files, File refFile) {
this.classname = name; this.classname = name;
this.files = files; this.files = files;
this.refFile = refFile;
} }
void run() throws Exception { void run() throws Exception {
// Test with each visitor // Test with each visitor
for (Class<Visitor> vclass : visitors) { for (Class<Visitor> vclass : visitors) {
boolean compResult = false;
try { try {
String vname = vclass.getName(); String vname = vclass.getName();
Constructor c = vclass.getConstructor(Tester.class); Constructor c = vclass.getConstructor(Tester.class);
@ -105,12 +124,21 @@ public class Tester {
e.printStackTrace(); e.printStackTrace();
} }
} }
info(sb.toString()); String output = sb.toString();
info(output);
compResult = compareOutput(refFile, output);
} catch(ReflectiveOperationException e) { } catch(ReflectiveOperationException e) {
warn("Class " + vclass.getName() + " ignored, not a Visitor"); warn("Class " + vclass.getName() + " ignored, not a Visitor");
continue; continue;
} }
if (!compResult) {
diffGolden++;
error("The output from " + vclass.getName() + " did not match golden file.");
} }
}
if (0 != diffGolden)
throw new Exception("Test output is not equal with golden file.");
if(0 != warnings) if(0 != warnings)
System.err.println("Test generated " + warnings + " warnings"); System.err.println("Test generated " + warnings + " warnings");
@ -119,6 +147,25 @@ public class Tester {
throw new Exception("Tester test failed with " + throw new Exception("Tester test failed with " +
errors + " errors"); errors + " errors");
} }
// Check if test output matches the golden file.
boolean compareOutput(File refFile, String sb)
throws FileNotFoundException, IOException {
List<String> refFileList = Files.readAllLines(refFile.toPath(), StandardCharsets.UTF_8);
List<String> sbList = Arrays.asList(sb.split(System.getProperty("line.separator")));
// Check if test output contains unexpected lines or is missing expected lines.
List<String> sbOnly = new ArrayList<String>(sbList);
sbOnly.removeAll(refFileList);
for (String line: sbOnly)
error("unexpected line found: " + line);
List<String> refOnly = new ArrayList<String>(refFileList);
refOnly.removeAll(sbList);
for (String line: refOnly)
error("expected line not found: " + line);
return sbOnly.isEmpty() && refOnly.isEmpty();
}
abstract static class Visitor { abstract static class Visitor {
Tester tester; Tester tester;
@ -153,9 +200,4 @@ public class Tester {
void info(String msg) { void info(String msg) {
System.out.println(msg); System.out.println(msg);
} }
int errors;
int warnings;
String classname;
File files[];
} }

View file

@ -27,7 +27,7 @@
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
* @build Tester * @build Tester
* @compile -parameters UncommonParamNames.java * @compile -parameters UncommonParamNames.java
* @run main Tester UncommonParamNames * @run main Tester UncommonParamNames UncommonParamNames.out
*/ */
/** Test uncommon parameter names */ /** Test uncommon parameter names */

View file

@ -0,0 +1,17 @@
class UncommonParamNames --
UncommonParamNames.<init>(zerozero)
UncommonParamNames.<init>(a)
UncommonParamNames.<init>($1)
UncommonParamNames.<init>(_x)
UncommonParamNames.<init>(a, ba, cba, dcba, edcba, fedcba, gfedcba, hgfedcba, ihgfedcba, jihgfedcba, kjihgfedcba, lkjihgfedcba, mlkjihgfedcba, nmlkjihgfedcba, onmlkjihgfedcba, ponmlkjihgfedcba, qponmlkjihgfedcba, rqponmlkjihgfedcba, srqponmlkjihgfedcba, tsrqponmlkjihgfedcba, utsrqponmlkjihgfedcba, vutsrqponmlkjihgfedcba, wvutsrqponmlkjihgfedcba, xwvutsrqponmlkjihgfedcba, yxwvutsrqponmlkjihgfedcba, zyxwvutsrqponmlkjihgfedcba)
UncommonParamNames.<init>(aLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName, baLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName, cbaLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName)
UncommonParamNames.<init>(zerozeroeight)
UncommonParamNames.<init>(zerozeroseven)
UncommonParamNames.foo(zerozero)
UncommonParamNames.foo(a)
UncommonParamNames.foo($1)
UncommonParamNames.foo(a, ba, cba, dcba, edcba, fedcba, gfedcba, hgfedcba, ihgfedcba, jihgfedcba, kjihgfedcba, lkjihgfedcba, mlkjihgfedcba, nmlkjihgfedcba, onmlkjihgfedcba, ponmlkjihgfedcba, qponmlkjihgfedcba, rqponmlkjihgfedcba, srqponmlkjihgfedcba, tsrqponmlkjihgfedcba, utsrqponmlkjihgfedcba, vutsrqponmlkjihgfedcba, wvutsrqponmlkjihgfedcba, xwvutsrqponmlkjihgfedcba, yxwvutsrqponmlkjihgfedcba, zyxwvutsrqponmlkjihgfedcba)
UncommonParamNames.foo(zerozeroseven)
UncommonParamNames.foo(zerozeroeight)
UncommonParamNames.foo(aLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName, baLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName, cbaLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongName)
UncommonParamNames.foo(_x)