CompoundScopeTest.java revision 981:671bb63f3ed5
1/* 2 * Copyright (c) 2011, 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 24/* 25 * @test 26 * @bug 7017664 7036906 27 * @summary Basher for CompoundScopes 28 */ 29 30import java.util.Random; 31import java.util.Map; 32import java.util.HashMap; 33import com.sun.tools.javac.util.*; 34import com.sun.tools.javac.code.*; 35import com.sun.tools.javac.code.Scope.*; 36import com.sun.tools.javac.code.Symbol.*; 37import com.sun.tools.javac.file.JavacFileManager; 38 39public class CompoundScopeTest { 40 public static void main(String... args) throws Exception { 41 new CompoundScopeTest().run(args); 42 } 43 44 static final int MAX_SYMBOLS_COUNT = 20; 45 static final int PASSES = 10; 46 47 void run(String... args) throws Exception { 48 int count = PASSES; 49 50 for (int i = 0; i < args.length; i++) { 51 String arg = args[i]; 52 if (arg.equals("-seed") && (i + 1 < args.length)) 53 seed = Long.parseLong(args[++i]); 54 else if(arg.equals("-tests") && (i + 1 < args.length)) 55 count = Integer.parseInt(args[++i]); 56 else 57 throw new Exception("unknown arg: " + arg); 58 } 59 60 rgen = new Random(seed); 61 62 for (int i = 0; i < count; i++) { 63 Test t = new Test(); 64 t.run(); 65 } 66 67 if (errors > 0) 68 throw new Exception(errors + " errors found"); 69 } 70 71 /** 72 * Write a message to stderr. 73 */ 74 void log(String msg) { 75 System.err.println(msg); 76 } 77 78 /** 79 * Write an error message to stderr. 80 */ 81 void error(String msg) { 82 System.err.println("Error: " + msg); 83 errors++; 84 } 85 86 Random rgen; 87 long seed = 0; 88 89 int errors; 90 91 /** Class to encapsulate a test run. */ 92 class Test { 93 94 List<Symbol> elems = List.nil(); 95 Map<Name, List<Symbol>> shadowedMap = new HashMap<Name, List<Symbol>>(); 96 97 /** Run the test. */ 98 void run() throws Exception { 99 log ("starting test"); 100 setup(); 101 Scope[] scopes = { createScope(rgen.nextInt(MAX_SYMBOLS_COUNT)), 102 createScope(rgen.nextInt(MAX_SYMBOLS_COUNT)), 103 createScope(rgen.nextInt(MAX_SYMBOLS_COUNT)) }; 104 boolean[][] scopeNesting = { {false, true, false, true}, 105 {false, true, true, true}, 106 {false, false, true, true} }; 107 /** 108 * We want to generate (and check) the following compound scopes: 109 * C1 = C(S1, S2, S3) 110 * C2 = C((S1, S2), S3) 111 * C3 = C(S1, (S2, S3)) 112 * C3 = C(C(S1, S2, S3)) 113 */ 114 for (int i = 0 ; i < 4 ; i ++) { 115 CompoundScope root = new CompoundScope(symtab.noSymbol); 116 CompoundScope sub = new CompoundScope(symtab.noSymbol); 117 boolean subAdded = false; 118 for (int sc = 0 ; sc < 3 ; sc ++) { 119 if (scopeNesting[sc][i]) { 120 sub.addSubScope(scopes[sc]); 121 if (!subAdded) { 122 root.addSubScope(sub); 123 subAdded = true; 124 } 125 } else { 126 root.addSubScope(scopes[sc]); 127 } 128 } 129 log("testing scope: " + root); 130 checkElems(root, null); 131 checkElems(root, new OddFilter()); 132 checkShadowed(root, null); 133 checkShadowed(root, new OddFilter()); 134 } 135 } 136 137 class OddFilter implements Filter<Symbol> { 138 public boolean accepts(Symbol s) { 139 Name numPart = s.name.subName(1, s.name.length()); 140 return Integer.parseInt(numPart.toString()) % 2 != 0; 141 } 142 } 143 144 /** 145 * Create a scope containing a given number of synthetic symbols 146 */ 147 Scope createScope(int nelems) { 148 Scope s = new Scope(symtab.noSymbol); 149 for (int i = 0 ; i < nelems ; i++) { 150 Symbol sym = new TypeSymbol(0, names.fromString("s" + i), null, null); 151 s.enter(sym); 152 elems = elems.prepend(sym); 153 List<Symbol> shadowed = shadowedMap.get(sym.name); 154 if (shadowed == null) { 155 shadowed = List.nil(); 156 } 157 shadowedMap.put(sym.name, shadowed.prepend(sym)); 158 } 159 return s; 160 } 161 162 /** 163 * Setup compiler context 164 */ 165 void setup() { 166 log ("setup"); 167 context = new Context(); 168 JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab 169 names = Names.instance(context); // Name.Table impls tied to an instance of Names 170 symtab = Symtab.instance(context); 171 } 172 173 /** 174 * Check that CompoundScope.getElements() correctly visits all symbols 175 * in all subscopes (in the correct order) 176 */ 177 void checkElems(CompoundScope cs, Filter<Symbol> sf) { 178 int count = 0; 179 ListBuffer<Symbol> found = ListBuffer.lb(); 180 List<Symbol> allSymbols = sf == null ? 181 elems : 182 filter(elems, sf); 183 int expectedCount = allSymbols.length(); 184 for (Symbol s : sf == null ? cs.getElements() : cs.getElements(sf)) { 185 checkSameSymbols(s, allSymbols.head); 186 allSymbols = allSymbols.tail; 187 found.append(s); 188 count++; 189 } 190 if (count != expectedCount) { 191 error("CompoundScope.getElements() did not returned enough symbols"); 192 } 193 } 194 195 /** 196 * Check that CompoundScope.getElements() correctly visits all symbols 197 * with a given name in all subscopes (in the correct order) 198 */ 199 void checkShadowed(CompoundScope cs, Filter<Symbol> sf) { 200 for (Map.Entry<Name, List<Symbol>> shadowedEntry : shadowedMap.entrySet()) { 201 int count = 0; 202 List<Symbol> shadowed = sf == null ? 203 shadowedEntry.getValue() : 204 filter(shadowedEntry.getValue(), sf); 205 int expectedCount = shadowed.length(); 206 Name name = shadowedEntry.getKey(); 207 for (Symbol s : sf == null ? cs.getElementsByName(name) : cs.getElementsByName(name, sf)) { 208 checkSameSymbols(s, shadowed.head); 209 shadowed = shadowed.tail; 210 count++; 211 } 212 if (count != expectedCount) { 213 error("CompoundScope.lookup() did not returned enough symbols for name " + name); 214 } 215 } 216 } 217 218 List<Symbol> filter(List<Symbol> elems, Filter<Symbol> sf) { 219 ListBuffer<Symbol> res = ListBuffer.lb(); 220 for (Symbol s : elems) { 221 if (sf.accepts(s)) { 222 res.append(s); 223 } 224 } 225 return res.toList(); 226 } 227 228 void checkSameSymbols(Symbol found, Symbol req) { 229 if (found != req) { 230 error("Symbol mismatch - found : " + found + ":" + found.hashCode() + "\n" + 231 " required : " + req + ":" + req.hashCode()); 232 } 233 } 234 235 Context context; 236 Symtab symtab; 237 Names names; 238 } 239} 240