blob: 6beae3afd8f111ee2428bebbd5b260467f7ff68d [file] [log] [blame]
/*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.lang.annotation.*;
import java.io.*;
import java.net.URL;
import java.util.List;
import com.sun.tools.classfile.*;
public class ClassfileTestHelper {
int expected_tinvisibles = 0;
int expected_tvisibles = 0;
int expected_invisibles = 0;
int expected_visibles = 0;
//Makes debugging much easier. Set to 'false' for less output.
public Boolean verbose = true;
void println(String msg) { if (verbose) System.out.println(msg); }
void print(String msg) { if (verbose) System.out.print(msg); }
File writeTestFile(String fname, String source) throws IOException {
File f = new File(fname);
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
out.println(source);
out.close();
return f;
}
File compile(File f) {
int rc = com.sun.tools.javac.Main.compile(new String[] {
"-g", f.getPath() });
if (rc != 0)
throw new Error("compilation failed. rc=" + rc);
String path = f.getPath();
return new File(path.substring(0, path.length() - 5) + ".class");
}
ClassFile getClassFile(String name) throws IOException, ConstantPoolException {
URL url = getClass().getResource(name);
InputStream in = url.openStream();
try {
return ClassFile.read(in);
} finally {
in.close();
}
}
ClassFile getClassFile(URL url) throws IOException, ConstantPoolException {
InputStream in = url.openStream();
try {
return ClassFile.read(in);
} finally {
in.close();
}
}
/************ Helper annotations counting methods ******************/
void test(ClassFile cf) {
test("CLASS",cf, null, null, Attribute.RuntimeVisibleTypeAnnotations, true);
test("CLASS",cf, null, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
//RuntimeAnnotations since one annotation can result in two attributes.
test("CLASS",cf, null, null, Attribute.RuntimeVisibleAnnotations, true);
test("CLASS",cf, null, null, Attribute.RuntimeInvisibleAnnotations, false);
}
void test(ClassFile cf, Field f, Boolean local) {
if (!local) {
test("FIELD",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true);
test("FIELD",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
test("FIELD",cf, f, null, Attribute.RuntimeVisibleAnnotations, true);
test("FIELD",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false);
} else {
test("CODE",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true);
test("CODE",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
test("CODE",cf, f, null, Attribute.RuntimeVisibleAnnotations, true);
test("CODE",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false);
}
}
void test(ClassFile cf, Field f) {
test(cf, f, false);
}
// 'local' determines whether to look for annotations in code attribute or not.
void test(ClassFile cf, Method m, Boolean local) {
if (!local) {
test("METHOD",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true);
test("METHOD",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
test("METHOD",cf, null, m, Attribute.RuntimeVisibleAnnotations, true);
test("METHOD",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false);
} else {
test("MCODE",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true);
test("MCODE",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
test("MCODE",cf, null, m, Attribute.RuntimeVisibleAnnotations, true);
test("MCODE",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false);
}
}
// default to not looking in code attribute
void test(ClassFile cf, Method m ) {
test(cf, m, false);
}
// Test the result of Attributes.getIndex according to expectations
// encoded in the class/field/method name; increment annotations counts.
void test(String ttype, ClassFile cf, Field f, Method m, String annName, boolean visible) {
String testtype = ttype;
String name = null;
int index = -1;
Attribute attr = null;
Code_attribute cAttr = null;
boolean isTAattr = annName.contains("TypeAnnotations");
try {
switch(testtype) {
case "FIELD":
name = f.getName(cf.constant_pool);
index = f.attributes.getIndex(cf.constant_pool, annName);
if(index!= -1)
attr = f.attributes.get(index);
break;
case "CODE":
name = f.getName(cf.constant_pool);
//fetch index of and code attribute and annotations from code attribute.
index = cf.attributes.getIndex(cf.constant_pool, Attribute.Code);
if(index!= -1) {
attr = cf.attributes.get(index);
assert attr instanceof Code_attribute;
cAttr = (Code_attribute)attr;
index = cAttr.attributes.getIndex(cf.constant_pool, annName);
if(index!= -1)
attr = cAttr.attributes.get(index);
}
break;
case "METHOD":
name = m.getName(cf.constant_pool);
index = m.attributes.getIndex(cf.constant_pool, annName);
if(index!= -1)
attr = m.attributes.get(index);
break;
case "MCODE":
name = m.getName(cf.constant_pool);
//fetch index of and code attribute and annotations from code attribute.
index = m.attributes.getIndex(cf.constant_pool, Attribute.Code);
if(index!= -1) {
attr = m.attributes.get(index);
assert attr instanceof Code_attribute;
cAttr = (Code_attribute)attr;
index = cAttr.attributes.getIndex(cf.constant_pool, annName);
if(index!= -1)
attr = cAttr.attributes.get(index);
}
break;
default:
name = cf.getName();
index = cf.attributes.getIndex(cf.constant_pool, annName);
if(index!= -1) attr = cf.attributes.get(index);
}
} catch(ConstantPoolException cpe) { cpe.printStackTrace(); }
if (index != -1) {
if(isTAattr) { //count RuntimeTypeAnnotations
RuntimeTypeAnnotations_attribute tAttr =
(RuntimeTypeAnnotations_attribute)attr;
println(testtype + ": " + name + ", " + annName + ": " +
tAttr.annotations.length );
if (tAttr.annotations.length > 0) {
for (int i = 0; i < tAttr.annotations.length; i++) {
println(" types:" + tAttr.annotations[i].position.type);
}
} else {
println("");
}
allt += tAttr.annotations.length;
if (visible)
tvisibles += tAttr.annotations.length;
else
tinvisibles += tAttr.annotations.length;
} else {
RuntimeAnnotations_attribute tAttr =
(RuntimeAnnotations_attribute)attr;
println(testtype + ": " + name + ", " + annName + ": " +
tAttr.annotations.length );
all += tAttr.annotations.length;
if (visible)
visibles += tAttr.annotations.length;
else
invisibles += tAttr.annotations.length;
}
}
}
void countAnnotations() {
errors=0;
int expected_allt = expected_tvisibles + expected_tinvisibles;
int expected_all = expected_visibles + expected_invisibles;
if (expected_allt != allt) {
errors++;
System.err.println("Failure: expected " + expected_allt +
" type annotations but found " + allt);
}
if (expected_all != all) {
errors++;
System.err.println("Failure: expected " + expected_all +
" annotations but found " + all);
}
if (expected_tvisibles != tvisibles) {
errors++;
System.err.println("Failure: expected " + expected_tvisibles +
" typevisible annotations but found " + tvisibles);
}
if (expected_tinvisibles != tinvisibles) {
errors++;
System.err.println("Failure: expected " + expected_tinvisibles +
" typeinvisible annotations but found " + tinvisibles);
}
allt=0;
tvisibles=0;
tinvisibles=0;
all=0;
visibles=0;
invisibles=0;
}
int errors;
int allt;
int tvisibles;
int tinvisibles;
int all;
int visibles;
int invisibles;
}