test/tools/javac/scope/StarImportTest.java

Mon, 07 Feb 2011 18:10:13 +0000

author
mcimadamore
date
Mon, 07 Feb 2011 18:10:13 +0000
changeset 858
96d4226bdd60
parent 767
7e3e9f6d013f
child 962
0ff2bbd38f10
permissions
-rw-r--r--

7007615: java_util/generics/phase2/NameClashTest02 fails since jdk7/pit/b123.
Summary: override clash algorithm is not implemented correctly
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2010, 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  */
    24 /*
    25  * @test
    26  * @bug 7004029
    27  * @summary Basher for star-import scopes
    28  */
    30 import java.lang.reflect.*;
    31 import java.util.*;
    32 import java.util.List;
    33 import com.sun.tools.javac.util.*;
    34 import com.sun.tools.javac.code.*;
    35 import com.sun.tools.javac.code.Scope.*;
    36 import com.sun.tools.javac.code.Symbol.*;
    37 import com.sun.tools.javac.file.JavacFileManager;
    38 import static com.sun.tools.javac.code.Kinds.*;
    40 public class StarImportTest {
    41     public static void main(String... args) throws Exception {
    42         new StarImportTest().run(args);
    43     }
    45     void run(String... args) throws Exception {
    46         int count = 1;
    48         for (int i = 0; i < args.length; i++) {
    49             String arg = args[i];
    50             if (arg.equals("-seed") && (i + 1 < args.length))
    51                 seed = Long.parseLong(args[++i]);
    52             else if(arg.equals("-tests") && (i + 1 < args.length))
    53                 count = Integer.parseInt(args[++i]);
    54             else
    55                 throw new Exception("unknown arg: " + arg);
    56         }
    58         rgen = new Random(seed);
    60         for (int i = 0; i < count; i++) {
    61             Test t = new Test();
    62             t.run();
    63         }
    65         if (errors > 0)
    66             throw new Exception(errors + " errors found");
    67     }
    69     /**
    70      * Select a random element from an array of choices.
    71      */
    72     <T> T random(T... choices) {
    73         return choices[rgen.nextInt(choices.length)];
    74     }
    76     /**
    77      * Write a message to stderr.
    78      */
    79     void log(String msg) {
    80         System.err.println(msg);
    81     }
    83     /**
    84      * Write a message to stderr, and dump a scope.
    85      */
    86     void log(String msg, Scope s) {
    87         System.err.print(msg);
    88         System.err.print(": ");
    89         String sep = "(";
    90         for (Scope.Entry se = s.elems; se != null; se = se.sibling) {
    91             for (Scope.Entry e = se; e.sym != null; e = e.next()) {
    92                 System.err.print(sep + e.sym.name + ":" + e.sym);
    93                 sep = ",";
    94             }
    95             System.err.print(")");
    96             sep = ", (";
    97         }
    98         System.err.println();
    99     }
   101     /**
   102      * Write an error message to stderr.
   103      */
   104     void error(String msg) {
   105         System.err.println("Error: " + msg);
   106         errors++;
   107     }
   109     Random rgen;
   110     long seed = 0;
   112     int errors;
   114     enum SetupKind { NAMES, PACKAGE, CLASS };
   115     static final int MAX_SETUP_COUNT = 50;
   116     static final int MAX_SETUP_NAME_COUNT = 20;
   117     static final int MAX_SETUP_PACKAGE_COUNT = 20;
   118     static final int MAX_SETUP_CLASS_COUNT = 20;
   120     /** Class to encapsulate a test run. */
   121     class Test {
   122         /** Run the test. */
   123         void run() throws Exception {
   124             log ("starting test");
   125             setup();
   126             createStarImportScope();
   127             test();
   128         }
   130         /**
   131          * Setup env by creating pseudo-random collection of names, packages and classes.
   132          */
   133         void setup() {
   134             log ("setup");
   135             context = new Context();
   136             JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab
   137             names = Names.instance(context);       // Name.Table impls tied to an instance of Names
   138             symtab = Symtab.instance(context);
   139             int setupCount = rgen.nextInt(MAX_SETUP_COUNT);
   140             for (int i = 0; i < setupCount; i++) {
   141                 switch (random(SetupKind.values())) {
   142                     case NAMES:
   143                         setupNames();
   144                         break;
   145                     case PACKAGE:
   146                         setupPackage();
   147                         break;
   148                     case CLASS:
   149                         setupClass();
   150                         break;
   151                 }
   152             }
   153         }
   155         /**
   156          * Set up a random number of names.
   157          */
   158         void setupNames() {
   159             int count = rgen.nextInt(MAX_SETUP_NAME_COUNT);
   160             log("setup: creating " + count + " new names");
   161             for (int i = 0; i < count; i++) {
   162                 names.fromString("n" + (++nextNameSerial));
   163             }
   164         }
   166         /**
   167          * Set up a package containing a random number of member elements.
   168          */
   169         void setupPackage() {
   170             Name name = names.fromString("p" + (++nextPackageSerial));
   171             int count = rgen.nextInt(MAX_SETUP_PACKAGE_COUNT);
   172             log("setup: creating package " + name + " with " + count + " entries");
   173             PackageSymbol p = new PackageSymbol(name, symtab.rootPackage);
   174             p.members_field = new Scope(p);
   175             for (int i = 0; i < count; i++) {
   176                 String outer = name + "c" + i;
   177                 String suffix = random(null, "$Entry", "$Entry2");
   178                 ClassSymbol c1 = createClass(names.fromString(outer), p);
   179 //                log("setup: created " + c1);
   180                 if (suffix != null) {
   181                     ClassSymbol c2 = createClass(names.fromString(outer + suffix), p);
   182 //                    log("setup: created " + c2);
   183                 }
   184             }
   185 //            log("package " + p, p.members_field);
   186             packages.add(p);
   187             imports.add(p);
   188         }
   190         /**
   191          * Set up a class containing a random number of member elements.
   192          */
   193         void setupClass() {
   194             Name name = names.fromString("c" + (++nextClassSerial));
   195             int count = rgen.nextInt(MAX_SETUP_CLASS_COUNT);
   196             log("setup: creating class " + name + " with " + count + " entries");
   197             ClassSymbol c = createClass(name, symtab.unnamedPackage);
   198 //            log("setup: created " + c);
   199             for (int i = 0; i < count; i++) {
   200                 ClassSymbol ic = createClass(names.fromString("Entry" + i), c);
   201 //                log("setup: created " + ic);
   202             }
   203             classes.add(c);
   204             imports.add(c);
   205         }
   207         /**
   208          * Create a star-import scope and a model therof, from the packages and
   209          * classes created by setupPackages and setupClasses.
   210          * @throws Exception for fatal errors, such as from reflection
   211          */
   212         void createStarImportScope() throws Exception {
   213             log ("createStarImportScope");
   214             PackageSymbol pkg = new PackageSymbol(names.fromString("pkg"), symtab.rootPackage);
   216             // if StarImportScope exists, use it, otherwise, for testing legacy code,
   217             // fall back on ImportScope
   218             Method importAll;
   219             try {
   220                 Class<?> c = Class.forName("com.sun.tools.javac.code.Scope$StarImportScope");
   221                 Constructor ctor = c.getDeclaredConstructor(new Class[] { Symbol.class });
   222                 importAll = c.getDeclaredMethod("importAll", new Class[] { Scope.class });
   223                 starImportScope = (Scope) ctor.newInstance(new Object[] { pkg });
   224             } catch (ClassNotFoundException e) {
   225                 starImportScope = new ImportScope(pkg);
   226                 importAll = null;
   227             }
   228             starImportModel = new Model();
   230             for (Symbol imp: imports) {
   231                 Scope members = imp.members();
   232                 if (importAll != null) {
   233 //                    log("importAll", members);
   234                     importAll.invoke(starImportScope, members);
   235                 } else {
   236                     Scope fromScope = members;
   237                     Scope toScope = starImportScope;
   238                     // The following lines are taken from MemberEnter.importAll,
   239                     // before the use of StarImportScope.importAll.
   240                     for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
   241                         if (e.sym.kind == TYP && !toScope.includes(e.sym))
   242                             toScope.enter(e.sym, fromScope);
   243                     }
   244                 }
   246                 for (Scope.Entry e = members.elems; e != null; e = e.sibling) {
   247                     starImportModel.enter(e.sym);
   248                 }
   249             }
   251 //            log("star-import scope", starImportScope);
   252             starImportModel.check(starImportScope);
   253         }
   255         /**
   256          * The core of the test. In a random order, move nested classes from
   257          * the package in which they created to the class which should own them.
   258          */
   259         void test() {
   260             log ("test");
   261             List<ClassSymbol> nestedClasses = new LinkedList<ClassSymbol>();
   262             for (PackageSymbol p: packages) {
   263                 for (Scope.Entry se = p.members_field.elems; se != null; se = se.sibling) {
   264                     if (se.sym.name.toString().contains("$"))
   265                         nestedClasses.add((ClassSymbol) se.sym);
   266                 }
   267             }
   269             for (int i = nestedClasses.size(); i > 0; i--) {
   270                 // select a random nested class to move from package to class
   271                 ClassSymbol sym = nestedClasses.remove(rgen.nextInt(i));
   272                 log("adjusting class " + sym);
   274                 // remove from star import model
   275                 starImportModel.remove(sym);
   277                 String s = sym.name.toString();
   278                 int dollar = s.indexOf("$");
   280                 // owner should be a package
   281                 assert (sym.owner.kind == PCK);
   283                 // determine new owner
   284                 Name outerName = names.fromString(s.substring(0, dollar));
   285 //                log(sym + " owner: " + sym.owner, sym.owner.members());
   286                 Scope.Entry outerEntry = sym.owner.members().lookup(outerName);
   287                 ClassSymbol outer = (ClassSymbol) outerEntry.sym;
   288 //                log("outer: " + outerName + " " + outer);
   290                 // remove from package
   291                 sym.owner.members().remove(sym);
   293                 // rename and insert into class
   294                 sym.name = names.fromString(s.substring(dollar + 1));
   295                 outer.members().enter(sym);
   296                 sym.owner = outer;
   298                 // verify
   299                 starImportModel.check(starImportScope);
   300             }
   301         }
   303         ClassSymbol createClass(Name name, Symbol owner) {
   304             ClassSymbol sym = new ClassSymbol(0, name, owner);
   305             sym.members_field = new Scope(sym);
   306             if (owner != symtab.unnamedPackage)
   307                 owner.members().enter(sym);
   308             return sym;
   309         }
   311         Context context;
   312         Symtab symtab;
   313         Names names;
   314         int nextNameSerial;
   315         List<PackageSymbol> packages = new ArrayList<PackageSymbol>();
   316         int nextPackageSerial;
   317         List<ClassSymbol> classes = new ArrayList<ClassSymbol>();
   318         List<Symbol> imports = new ArrayList<Symbol>();
   319         int nextClassSerial;
   321         Scope starImportScope;
   322         Model starImportModel;
   323     }
   325     class Model {
   326         private Map<Name, Set<Symbol>> map = new HashMap<Name, Set<Symbol>>();
   327         private Set<Symbol> bogus = new HashSet<Symbol>();
   329         void enter(Symbol sym) {
   330             Set<Symbol> syms = map.get(sym.name);
   331             if (syms == null)
   332                 map.put(sym.name, syms = new LinkedHashSet<Symbol>());
   333             syms.add(sym);
   334         }
   336         void remove(Symbol sym) {
   337             Set<Symbol> syms = map.get(sym.name);
   338             if (syms == null)
   339                 error("no entries for " + sym.name + " found in reference model");
   340             else {
   341                 boolean ok = syms.remove(sym);
   342                 if (ok) {
   343 //                        log(sym.name + "(" + sym + ") removed from reference model");
   344                 } else {
   345                     error(sym.name + " not found in reference model");
   346                 }
   347                 if (syms.isEmpty())
   348                     map.remove(sym.name);
   349             }
   350         }
   352         /**
   353          * Check the contents of a scope
   354          */
   355         void check(Scope scope) {
   356             // First, check all entries in scope are in map
   357             int bogusCount = 0;
   358             for (Scope.Entry se = scope.elems; se != null; se = se.sibling) {
   359                 Symbol sym = se.sym;
   360                 if (sym.owner != se.scope.owner) {
   361                     if (bogus.contains(sym)) {
   362                         bogusCount++;
   363                     } else {
   364                         log("Warning: " + sym.name + ":" + sym + " appears to be bogus");
   365                         bogus.add(sym);
   366                     }
   367                 } else {
   368                     Set<Symbol> syms = map.get(sym.name);
   369                     if (syms == null) {
   370                         error("check: no entries found for " + sym.name + ":" + sym + " in reference map");
   371                     } else  if (!syms.contains(sym)) {
   372                         error("check: symbol " + sym.name + ":" + sym + " not found in reference map");
   373                     }
   374                 }
   375             }
   376             if (bogusCount > 0) {
   377                 log("Warning: " + bogusCount + " other bogus entries previously reported");
   378             }
   380             // Second, check all entries in map are in scope
   381             for (Map.Entry<Name,Set<Symbol>> me: map.entrySet()) {
   382                 Name name = me.getKey();
   383                 Scope.Entry se = scope.lookup(name);
   384                 assert (se != null);
   385                 if (se.sym == null) {
   386                     error("check: no entries found for " + name + " in scope");
   387                     continue;
   388                 }
   389             nextSym:
   390                 for (Symbol sym: me.getValue()) {
   391                     for (Scope.Entry e = se; e.sym != null; e = e.next()) {
   392                         if (sym == e.sym)
   393                             continue nextSym;
   394                     }
   395                     error("check: symbol " + sym + " not found in scope");
   396                 }
   397             }
   398         }
   399     }
   400 }

mercurial