MethodParametersTester.java revision 3581:64fd589ab53a
1/* 2 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import java.io.*; 25import java.lang.reflect.Constructor; 26import java.nio.charset.StandardCharsets; 27import java.nio.file.Files; 28import java.util.ArrayList; 29import java.util.Arrays; 30import java.util.List; 31 32/** 33 * Test driver for MethodParameters testing. 34 * <p> 35 * The intended use of this driver is to run it, giving the name of 36 * a single class compiled with -parameters as argument. The driver 37 * will test the specified class, and any nested classes it finds. 38 * <p> 39 * Each class is tested in two way. By refelction, and by directly 40 * checking MethodParameters attributes in the classfile. The checking 41 * is done using two visitor classes {@link ClassFileVisitor} and 42 * {@link ReflectionVisitor}. 43 * <p> 44 * The {@code ReflectionVisitor} test logically belongs with library tests. 45 * we wish to reuse the same test-cases, so both test are committed together, 46 * under langtools. The tests, may be duplicated in the jdk repository. 47 */ 48public class MethodParametersTester { 49 50 final static File classesdir = new File(System.getProperty("test.classes", ".")); 51 52 private String classname; 53 private File[] files; 54 private File refFile; 55 private int errors; 56 private int warnings; 57 private int diffGolden; 58 59 /** 60 * The visitor classes that does the actual checking are referenced 61 * statically, to force compilations, without having to reference 62 * them in individual test cases. 63 * <p> 64 * This makes it easy to change the set of visitors, without 65 * complicating the design with dynamic discovery and compilation 66 * of visitor classes. 67 */ 68 static final Class visitors[] = { 69 ClassFileVisitor.class, 70 ReflectionVisitor.class 71 }; 72 73 /** 74 * Test-driver expect a single classname as argument. 75 */ 76 public static void main(String... args) throws Exception { 77 if (args.length != 2) { 78 throw new Error("A single class name and a golden file are expected as argument"); 79 } 80 String testSrc = System.getProperty("test.src"); 81 String testName = args[0]; 82 String testGoldenFile = args[1]; 83 final String pattern = testName + ".*\\.class"; 84 File refFile = new File(testSrc, testGoldenFile); 85 File[] files = classesdir.listFiles(new FileFilter() { 86 public boolean accept(File f) { 87 return f.getName().matches(pattern); 88 } 89 }); 90 if (files.length == 0) { 91 File file = new File(classesdir, testName + ".class"); 92 throw new Error(file.getPath() + " not found"); 93 } 94 95 new MethodParametersTester(testName, files, refFile).run(); 96 } 97 98 public MethodParametersTester(String name, File[] files, File refFile) { 99 this.classname = name; 100 this.files = files; 101 this.refFile = refFile; 102 } 103 104 void run() throws Exception { 105 106 // Test with each visitor 107 for (Class<Visitor> vclass : visitors) { 108 boolean compResult = false; 109 try { 110 String vname = vclass.getName(); 111 Constructor c = vclass.getConstructor(MethodParametersTester.class); 112 113 info("\nRun " + vname + " for " + classname + "\n"); 114 StringBuilder sb = new StringBuilder(); 115 for (File f : files) { 116 String fname = f.getName(); 117 fname = fname.substring(0, fname.length() - 6); 118 Visitor v = (Visitor) c.newInstance(this); 119 try { 120 v.visitClass(fname, f, sb); 121 } catch(Exception e) { 122 error("Uncaught exception in visitClass()"); 123 e.printStackTrace(); 124 } 125 } 126 String output = sb.toString(); 127 info(output); 128 compResult = compareOutput(refFile, output); 129 } catch(ReflectiveOperationException e) { 130 warn("Class " + vclass.getName() + " ignored, not a Visitor"); 131 continue; 132 } 133 if (!compResult) { 134 diffGolden++; 135 error("The output from " + vclass.getName() + " did not match golden file."); 136 } 137 } 138 139 if (0 != diffGolden) 140 throw new Exception("Test output is not equal with golden file."); 141 142 if(0 != warnings) 143 System.err.println("Test generated " + warnings + " warnings"); 144 145 if(0 != errors) 146 throw new Exception("Tester test failed with " + 147 errors + " errors"); 148 } 149 // Check if test output matches the golden file. 150 boolean compareOutput(File refFile, String sb) 151 throws FileNotFoundException, IOException { 152 153 List<String> refFileList = Files.readAllLines(refFile.toPath(), StandardCharsets.UTF_8); 154 List<String> sbList = Arrays.asList(sb.split("[\r\n]+")); 155 // Check if test output contains unexpected lines or is missing expected lines. 156 List<String> sbOnly = new ArrayList<>(sbList); 157 sbOnly.removeAll(refFileList); 158 for (String line: sbOnly) 159 error("unexpected line found: " + line); 160 161 List<String> refOnly = new ArrayList<>(refFileList); 162 refOnly.removeAll(sbList); 163 for (String line: refOnly) 164 error("expected line not found: " + line); 165 166 return sbOnly.isEmpty() && refOnly.isEmpty(); 167 } 168 169 abstract static class Visitor { 170 MethodParametersTester tester; 171 File classesdir; 172 173 public Visitor(MethodParametersTester tester) { 174 this.tester = tester; 175 } 176 177 abstract void visitClass(final String classname, final File cfile, 178 final StringBuilder sb) throws Exception; 179 180 public void error(String msg) { 181 tester.error(msg); 182 } 183 184 public void warn(String msg) { 185 tester.warn(msg); 186 } 187 } 188 189 void error(String msg) { 190 System.err.println("Error: " + msg); 191 errors++; 192 } 193 194 void warn(String msg) { 195 System.err.println("Warning: " + msg); 196 warnings++; 197 } 198 199 void info(String msg) { 200 System.out.println(msg); 201 } 202} 203