8023520: Add missing test for JDK-7118412

Wed, 21 Aug 2013 20:41:42 -0400

author
emc
date
Wed, 21 Aug 2013 20:41:42 -0400
changeset 1972
eebb29618f50
parent 1971
57e1266527dd
child 1973
7a4717f3ea7b

8023520: Add missing test for JDK-7118412
Summary: The test for JDK-7118412 was dropped from the changeset in a merging accident.
Reviewed-by: jjg

test/tools/javac/7118412/ShadowingTest.java file | annotate | diff | comparison | revisions
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/test/tools/javac/7118412/ShadowingTest.java	Wed Aug 21 20:41:42 2013 -0400
     1.3 @@ -0,0 +1,287 @@
     1.4 +/*
     1.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + */
    1.26 +
    1.27 +/*
    1.28 + * @test
    1.29 + * @bug 7118412
    1.30 + * @summary Shadowing of type-variables vs. member types
    1.31 + */
    1.32 +import java.io.File;
    1.33 +import java.io.FileWriter;
    1.34 +import java.io.IOException;
    1.35 +import java.io.PrintWriter;
    1.36 +import java.io.StringWriter;
    1.37 +
    1.38 +public class ShadowingTest {
    1.39 +
    1.40 +    // We generate a method "test" that tries to call T.<something,
    1.41 +    // depending on the value of MethodCall>.  This controls whether
    1.42 +    // "test" is static or not.
    1.43 +    private enum MethodContext {
    1.44 +        STATIC("static "),
    1.45 +        INSTANCE("");
    1.46 +
    1.47 +        public final String methodcontext;
    1.48 +
    1.49 +        MethodContext(final String methodcontext) {
    1.50 +            this.methodcontext = methodcontext;
    1.51 +        }
    1.52 +    }
    1.53 +
    1.54 +    // These control whether or not a type parameter, method type
    1.55 +    // parameter, or inner class get declared (and in the case of
    1.56 +    // inner classes, whether it's static or not.
    1.57 +
    1.58 +    private enum MethodTypeParameterDecl {
    1.59 +        NO(""),
    1.60 +        YES("<T extends Number> ");
    1.61 +
    1.62 +        public final String tyvar;
    1.63 +
    1.64 +        MethodTypeParameterDecl(final String tyvar) {
    1.65 +            this.tyvar = tyvar;
    1.66 +        }
    1.67 +    }
    1.68 +
    1.69 +    private enum InsideDef {
    1.70 +        NONE(""),
    1.71 +        STATIC("static class T { public void inner() {} }\n"),
    1.72 +        INSTANCE("class T { public void inner() {} }\n");
    1.73 +
    1.74 +        public final String instancedef;
    1.75 +
    1.76 +        InsideDef(final String instancedef) {
    1.77 +            this.instancedef = instancedef;
    1.78 +        }
    1.79 +    }
    1.80 +
    1.81 +    private enum TypeParameterDecl {
    1.82 +        NO(""),
    1.83 +        YES("<T extends Collection>");
    1.84 +
    1.85 +        public final String tyvar;
    1.86 +
    1.87 +        TypeParameterDecl(final String tyvar) {
    1.88 +            this.tyvar = tyvar;
    1.89 +        }
    1.90 +    }
    1.91 +
    1.92 +    // Represents what method we try to call.  This is a way of
    1.93 +    // checking which T we're seeing.
    1.94 +    private enum MethodCall {
    1.95 +        // Method type variables extend Number, so we have intValue
    1.96 +        METHOD_TYPEVAR("intValue"),
    1.97 +        // The inner class declaration has a method called "inner"
    1.98 +        INNER_CLASS("inner"),
    1.99 +        // The class type variables extend Collection, so we call iterator
   1.100 +        TYPEVAR("iterator"),
   1.101 +        // The outer class declaration has a method called "outer"
   1.102 +        OUTER_CLASS("outer");
   1.103 +
   1.104 +        public final String methodcall;
   1.105 +
   1.106 +        MethodCall(final String methodcall) {
   1.107 +            this.methodcall = methodcall;
   1.108 +        }
   1.109 +
   1.110 +    }
   1.111 +
   1.112 +    public boolean succeeds(final MethodCall call,
   1.113 +                            final MethodTypeParameterDecl mtyvar,
   1.114 +                            final MethodContext ctx,
   1.115 +                            final InsideDef inside,
   1.116 +                            final TypeParameterDecl tyvar) {
   1.117 +        switch(call) {
   1.118 +            // We want to resolve to the method type variable
   1.119 +        case METHOD_TYPEVAR: switch(mtyvar) {
   1.120 +                // If the method type variable exists, then T will
   1.121 +                // resolve to it, and we'll have intValue.
   1.122 +            case YES: return true;
   1.123 +                // Otherwise, this cannot succeed.
   1.124 +            default: return false;
   1.125 +            }
   1.126 +            // We want to resolve to the inner class
   1.127 +        case INNER_CLASS: switch(mtyvar) {
   1.128 +                // The method type parameter will shadow the inner
   1.129 +                // class, so there can't be one.
   1.130 +            case NO: switch(ctx) {
   1.131 +                    // If we're not static, then either one should succeed.
   1.132 +                case INSTANCE: switch(inside) {
   1.133 +                    case INSTANCE:
   1.134 +                    case STATIC:
   1.135 +                        return true;
   1.136 +                    default: return false;
   1.137 +                    }
   1.138 +                case STATIC: switch(inside) {
   1.139 +                        // If we are static, and the inner class is
   1.140 +                        // static, then we also succeed, because we
   1.141 +                        // can't see the type variable.
   1.142 +                    case STATIC: return true;
   1.143 +                    case INSTANCE: switch(tyvar) {
   1.144 +                            // If we're calling from a non-static
   1.145 +                            // context, there can't be a class type
   1.146 +                            // variable, because that will shadow the
   1.147 +                            // static inner class definition.
   1.148 +                        case NO: return true;
   1.149 +                        default: return false;
   1.150 +                        }
   1.151 +                        // If the inner class isn't declared, we can't
   1.152 +                        // see it.
   1.153 +                    default: return false;
   1.154 +                    }
   1.155 +                    // Can't get here.
   1.156 +                default: return false;
   1.157 +                }
   1.158 +            default: return false;
   1.159 +            }
   1.160 +            // We want to resolve to the class type parameter
   1.161 +        case TYPEVAR: switch(mtyvar) {
   1.162 +                // We can't have a method type parameter, as that would
   1.163 +                // shadow the class type parameter
   1.164 +            case NO: switch(ctx) {
   1.165 +                case INSTANCE: switch(inside) {
   1.166 +                        // We have to be in an instance context.  If
   1.167 +                        // we're static, we can't see the type
   1.168 +                        // variable.
   1.169 +                    case NONE: switch(tyvar) {
   1.170 +                            // Obviously, the type parameter has to be declared.
   1.171 +                        case YES: return true;
   1.172 +                        default: return false;
   1.173 +                        }
   1.174 +                    default: return false;
   1.175 +                    }
   1.176 +                default: return false;
   1.177 +                }
   1.178 +            default: return false;
   1.179 +            }
   1.180 +            // We want to resolve to the outer class
   1.181 +        case OUTER_CLASS: switch(mtyvar) {
   1.182 +            case NO: switch(inside) {
   1.183 +                case NONE: switch(tyvar) {
   1.184 +                        // Basically, nothing else can be declared, or
   1.185 +                        // else we can't see it.  Even if our context
   1.186 +                        // is static, the compiler will complain if
   1.187 +                        // non-static T's exist, because they will
   1.188 +                        // shadow the outer class.
   1.189 +                    case NO: return true;
   1.190 +                    default: return false;
   1.191 +                    }
   1.192 +                default: return false;
   1.193 +                }
   1.194 +            default: return false;
   1.195 +            }
   1.196 +        }
   1.197 +        return false;
   1.198 +    }
   1.199 +
   1.200 +    private static final File classesdir = new File("7118412");
   1.201 +
   1.202 +    private int errors = 0;
   1.203 +
   1.204 +    private int dirnum = 0;
   1.205 +
   1.206 +    private void doTest(final MethodTypeParameterDecl mtyvar,
   1.207 +                        final TypeParameterDecl tyvar,
   1.208 +                        final InsideDef insidedef, final MethodContext ctx,
   1.209 +                        final MethodCall call)
   1.210 +        throws IOException {
   1.211 +        final String content = "import java.util.Collection;\n" +
   1.212 +            "class Test" + tyvar.tyvar + " {\n" +
   1.213 +            "  " + insidedef.instancedef +
   1.214 +            "  " + ctx.methodcontext + mtyvar.tyvar + "void test(T t) { t." +
   1.215 +            call.methodcall + "(); }\n" +
   1.216 +            "}\n" +
   1.217 +            "class T { void outer() {} }\n";
   1.218 +        final File dir = new File(classesdir, "" + dirnum);
   1.219 +        final File Test_java = writeFile(dir, "Test.java", content);
   1.220 +        dirnum++;
   1.221 +        if(succeeds(call, mtyvar, ctx, insidedef, tyvar)) {
   1.222 +            if(!assert_compile_succeed(Test_java))
   1.223 +                System.err.println("Failed file:\n" + content);
   1.224 +        }
   1.225 +        else {
   1.226 +            if(!assert_compile_fail(Test_java))
   1.227 +                System.err.println("Failed file:\n" + content);
   1.228 +        }
   1.229 +    }
   1.230 +
   1.231 +    private void run() throws Exception {
   1.232 +        classesdir.mkdir();
   1.233 +        for(MethodTypeParameterDecl mtyvar : MethodTypeParameterDecl.values())
   1.234 +            for(TypeParameterDecl tyvar : TypeParameterDecl.values())
   1.235 +                for(InsideDef insidedef : InsideDef.values())
   1.236 +                    for(MethodContext ctx : MethodContext.values())
   1.237 +                        for(MethodCall methodcall : MethodCall.values())
   1.238 +                            doTest(mtyvar, tyvar, insidedef, ctx, methodcall);
   1.239 +        if (errors != 0)
   1.240 +            throw new Exception("ShadowingTest test failed with " +
   1.241 +                                errors + " errors.");
   1.242 +    }
   1.243 +
   1.244 +    private boolean assert_compile_fail(final File file) {
   1.245 +        final String filename = file.getPath();
   1.246 +        final String[] args = { filename };
   1.247 +        final StringWriter sw = new StringWriter();
   1.248 +        final PrintWriter pw = new PrintWriter(sw);
   1.249 +        final int rc = com.sun.tools.javac.Main.compile(args, pw);
   1.250 +        pw.close();
   1.251 +        if (rc == 0) {
   1.252 +            System.err.println("Compilation of " + file.getName() +
   1.253 +                               " didn't fail as expected.");
   1.254 +            errors++;
   1.255 +            return false;
   1.256 +        } else return true;
   1.257 +    }
   1.258 +
   1.259 +    private boolean assert_compile_succeed(final File file) {
   1.260 +        final String filename = file.getPath();
   1.261 +        final String[] args = { filename };
   1.262 +        final StringWriter sw = new StringWriter();
   1.263 +        final PrintWriter pw = new PrintWriter(sw);
   1.264 +        final int rc = com.sun.tools.javac.Main.compile(args, pw);
   1.265 +        pw.close();
   1.266 +        if (rc != 0) {
   1.267 +            System.err.println("Compilation of " + file.getName() +
   1.268 +                               " didn't succeed as expected.  Output:");
   1.269 +            System.err.println(sw.toString());
   1.270 +            errors++;
   1.271 +            return false;
   1.272 +        } else return true;
   1.273 +    }
   1.274 +
   1.275 +    private File writeFile(final File dir,
   1.276 +                           final String path,
   1.277 +                           final String body) throws IOException {
   1.278 +        final File f = new File(dir, path);
   1.279 +        f.getParentFile().mkdirs();
   1.280 +        final FileWriter out = new FileWriter(f);
   1.281 +        out.write(body);
   1.282 +        out.close();
   1.283 +        return f;
   1.284 +    }
   1.285 +
   1.286 +    public static void main(String... args) throws Exception {
   1.287 +        new ShadowingTest().run();
   1.288 +    }
   1.289 +
   1.290 +}

mercurial