1 /*
   2  * Copyright (c) 2017, 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 8046171
  27  * @summary Test the various rules for nest members and nest-hosts
  28  * @compile TestNestmateMembership.java
  29  *          PackagedNestHost.java
  30  *          PackagedNestHost2.java
  31  *
  32  * @compile TargetNoHost.jcod
  33  *          CallerNoHost.jcod
  34  *          TargetMissingHost.jcod
  35  *          CallerMissingHost.jcod
  36  *          CallerNotInstanceHost.jcod
  37  *          TargetNotInstanceHost.jcod
  38  *          CallerNotOurHost.jcod
  39  *          TargetNotOurHost.jcod
  40  *          PackagedNestHost.jcod
  41  *          PackagedNestHost2Member.jcod
  42  *          PackagedNestHostMember.jcod
  43  *
  44  * @run main/othervm TestNestmateMembership
  45  */
  46 
  47 // We test all the "illegal" relationships between a nest member and its nest-host
  48 // except for the case where the name of the nest-member matches the name listed
  49 // in the nest-host, but resolves to a different class. There doesn't seem to
  50 // be a way to construct that scenario.
  51 // For each nested class below there is a corresponding .jcod file which breaks one
  52 // of the rules regarding nest membership. For the package related tests we have
  53 // additional PackageNestHost*.java sources.
  54 // Note that all the .java files must be compiled in the same step, while all
  55 // .jcod files must be compiled in a later step.
  56 
  57 // As access checking requires resolution and validation of the nest-host of
  58 // both the caller class and the target class, we must check that all
  59 // combinations of good/bad caller/target are checked for each of the
  60 // possible errors:
  61 // - no nest-host attribute
  62 // - nest-host class can not be found
  63 // - nest-host class is not an instance class
  64 // - class is not a member of nest-host's nest
  65 // - class and nest-host are in different packages
  66 
  67 public class TestNestmateMembership {
  68 
  69     static class Caller {
  70         private static void m() {
  71             System.out.println("Caller.m()");
  72         }
  73         public static void invokeTarget() {
  74             Target.m();
  75         }
  76         public static void invokeTargetNoHost() {
  77             TargetNoHost.m();
  78         }
  79         public static void invokeTargetMissingHost() {
  80             TargetMissingHost.m();
  81         }
  82         public static void invokeTargetNotInstanceHost() {
  83             TargetNotInstanceHost.m();
  84         }
  85         public static void invokeTargetNotOurHost() {
  86             TargetNotOurHost.m();
  87         }
  88     }
  89 
  90     static class CallerNoHost {
  91         private static void m() {
  92             System.out.println("CallerNoHost.m() - java version");
  93         }
  94         public static void invokeTarget() {
  95             Target.m();
  96         }
  97         public static void invokeTargetNoHost() {
  98             TargetNoHost.m();
  99         }
 100     }
 101 
 102     static class CallerMissingHost {
 103         String msg = "NoCallerMissingHost"; // for cp entry
 104         private static void m() {
 105             System.out.println("CallerMissingHost.m() - java version");
 106         }
 107         public static void invokeTarget() {
 108             Target.m();
 109         }
 110         public static void invokeTargetMissingHost() {
 111             TargetMissingHost.m();
 112         }
 113     }
 114 
 115     static class CallerNotInstanceHost {
 116         Object[] oa; // create CP entry to use in jcod change
 117         private static void m() {
 118             System.out.println("CallerNotInstanceHost.m() - java version");
 119         }
 120         public static void invokeTarget() {
 121             Target.m();
 122         }
 123         public static void invokeTargetNotInstanceHost() {
 124             TargetNotInstanceHost.m();
 125         }
 126     }
 127 
 128     static class CallerNotOurHost {
 129         private static void m() {
 130             System.out.println("CallerNotOurHost.m() - java version");
 131         }
 132         public static void invokeTarget() {
 133             Target.m();
 134         }
 135         public static void invokeTargetNotOurHost() {
 136             TargetNotOurHost.m();
 137         }
 138     }
 139 
 140     static class Target {
 141         private static void m() {
 142             System.out.println("Target.m()");
 143         }
 144     }
 145 
 146     static class TargetNoHost {
 147         private static void m() {
 148             System.out.println("TargetNoHost.m() - java version");
 149         }
 150     }
 151 
 152     static class TargetMissingHost {
 153         String msg = "NoTargetMissingHost";  // for cp entry
 154         private static void m() {
 155             System.out.println("TargetMissingHost.m() - java version");
 156         }
 157     }
 158 
 159     static class TargetNotInstanceHost {
 160         Object[] oa; // create CP entry to use in jcod change
 161         private static void m() {
 162             System.out.println("TargetNotInstanceHost.m() - java version");
 163         }
 164     }
 165 
 166     static class TargetNotOurHost {
 167         private static void m() {
 168             System.out.println("TargetNotOurHost.m() - java version");
 169         }
 170     }
 171 
 172     public static void main(String[] args) throws Throwable {
 173         test_GoodCalls();
 174         test_NoHost();
 175         test_MissingHost();
 176         test_NotInstanceHost();
 177         test_NotOurHost();
 178         test_WrongPackageHost();
 179     }
 180 
 181     static void test_GoodCalls(){
 182         try {
 183             Caller.invokeTarget();
 184         }
 185         catch (Exception e) {
 186             throw new Error("Unexpected exception on good calls: " + e);
 187         }
 188     }
 189 
 190     static void test_NoHost() throws Throwable {
 191         System.out.println("Testing for missing nest-host attribute");
 192         String msg = "tried to access method " +
 193             "TestNestmateMembership$TargetNoHost.m()V from class " +
 194             "TestNestmateMembership$Caller";
 195         try {
 196             Caller.invokeTargetNoHost();
 197             throw new Error("Missing IllegalAccessError: " + msg);
 198         }
 199         catch (IllegalAccessError expected) {
 200             check_expected(expected, msg);
 201         }
 202         msg = "tried to access method TestNestmateMembership$Target.m()V" +
 203             " from class TestNestmateMembership$CallerNoHost";
 204         try {
 205             CallerNoHost.invokeTarget();
 206             throw new Error("Missing IllegalAccessError: " + msg);
 207         }
 208         catch (IllegalAccessError expected) {
 209             check_expected(expected, msg);
 210         }
 211         msg = "tried to access method TestNestmateMembership$TargetNoHost.m()V" +
 212             " from class TestNestmateMembership$CallerNoHost";
 213         try {
 214             CallerNoHost.invokeTargetNoHost();
 215             throw new Error("Missing IllegalAccessError: " + msg);
 216         }
 217         catch (IllegalAccessError expected) {
 218             check_expected(expected, msg);
 219         }
 220     }
 221 
 222     static void test_MissingHost() throws Throwable {
 223         System.out.println("Testing for nest-host class that does not exist");
 224         String msg = "Unable to load nest-host class of " +
 225             "TestNestmateMembership$TargetMissingHost";
 226         String cause_msg = "NoTargetMissingHost";
 227         try {
 228             Caller.invokeTargetMissingHost();
 229             throw new Error("Missing NoClassDefFoundError: " + msg);
 230         }
 231         catch (NoClassDefFoundError expected) {
 232             check_expected(expected, msg);
 233             Throwable cause = expected.getCause();
 234             if (cause instanceof NoClassDefFoundError) {
 235                 check_expected(cause, cause_msg);
 236             }
 237             else throw new Error("Unexpected NoClassDefFoundError", expected);
 238         }
 239         msg = "Unable to load nest-host class of " +
 240             "TestNestmateMembership$CallerMissingHost";
 241         cause_msg = "NoCallerMissingHost";
 242         try {
 243             CallerMissingHost.invokeTarget();
 244             throw new Error("Missing NoClassDefFoundError: " + msg);
 245         }
 246         catch (NoClassDefFoundError expected) {
 247             check_expected(expected, msg);
 248             Throwable cause = expected.getCause();
 249             if (cause instanceof NoClassDefFoundError) {
 250                 check_expected(cause, cause_msg);
 251             }
 252             else throw new Error("Unexpected NoClassDefFoundError", expected);
 253         }
 254         msg = "Unable to load nest-host class of "+
 255             "TestNestmateMembership$CallerMissingHost";
 256         cause_msg = "NoCallerMissingHost";
 257         try {
 258             CallerMissingHost.invokeTargetMissingHost();
 259             throw new Error("Missing NoClassDefFoundError: " + msg);
 260         }
 261         catch (NoClassDefFoundError expected) {
 262             check_expected(expected, msg);
 263             Throwable cause = expected.getCause();
 264             if (cause instanceof NoClassDefFoundError) {
 265                 check_expected(cause, cause_msg);
 266             }
 267             else throw new Error("Unexpected NoClassDefFoundError", expected);
 268         }
 269     }
 270 
 271     static void test_NotInstanceHost() throws Throwable {
 272         System.out.println("Testing for nest-host class that is not an instance class");
 273         String msg = "Type TestNestmateMembership$TargetNotInstanceHost is not a "+
 274             "nest member of [Ljava.lang.Object;: nest-host is not an instance class";
 275         try {
 276             Caller.invokeTargetNotInstanceHost();
 277             throw new Error("Missing IllegalAccessError: " + msg);
 278         }
 279         catch (IllegalAccessError expected) {
 280             check_expected(expected, msg);
 281         }
 282         msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
 283             "nest member of [Ljava.lang.Object;: nest-host is not an instance class";
 284         try {
 285             CallerNotInstanceHost.invokeTarget();
 286             throw new Error("Missing IllegalAccessError: " + msg);
 287         }
 288         catch (IllegalAccessError expected) {
 289             check_expected(expected, msg);
 290         }
 291         msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
 292             "nest member of [Ljava.lang.Object;: nest-host is not an instance class";
 293         try {
 294             CallerNotInstanceHost.invokeTargetNotInstanceHost();
 295             throw new Error("Missing IllegalAccessError: " + msg);
 296         }
 297         catch (IllegalAccessError expected) {
 298             check_expected(expected, msg);
 299         }
 300     }
 301 
 302     static void test_NotOurHost() throws Throwable {
 303         System.out.println("Testing for nest-host class that does not list us in its nest");
 304         String msg = "Type TestNestmateMembership$TargetNotOurHost is not a nest member" +
 305             " of java.lang.Object: current type is not listed as a nest member";
 306         try {
 307             Caller.invokeTargetNotOurHost();
 308             throw new Error("Missing IllegalAccessError: " + msg);
 309         }
 310         catch (IllegalAccessError expected) {
 311             check_expected(expected, msg);
 312         }
 313         msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
 314             " of java.lang.Object: current type is not listed as a nest member";
 315         try {
 316             CallerNotOurHost.invokeTarget();
 317             throw new Error("Missing IllegalAccessError: " + msg);
 318         }
 319         catch (IllegalAccessError expected) {
 320             check_expected(expected, msg);
 321         }
 322         msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
 323             " of java.lang.Object: current type is not listed as a nest member";
 324         try {
 325             CallerNotOurHost.invokeTargetNotOurHost();
 326             throw new Error("Missing IllegalAccessError: " + msg);
 327         }
 328         catch (IllegalAccessError expected) {
 329             check_expected(expected, msg);
 330         }
 331     }
 332 
 333     static void test_WrongPackageHost() {
 334         System.out.println("Testing for nest-host and nest-member in different packages");
 335         String msg = "Type P2.PackagedNestHost2$Member is not a nest member of " +
 336             "P1.PackagedNestHost: types are in different packages";
 337         try {
 338             P1.PackagedNestHost.doAccess();
 339             throw new Error("Missing IllegalAccessError: " + msg);
 340         }
 341         catch (IllegalAccessError expected) {
 342             check_expected(expected, msg);
 343         }
 344         try {
 345             P2.PackagedNestHost2.Member.doAccess();
 346             throw new Error("Missing IllegalAccessError: " + msg);
 347         }
 348         catch (IllegalAccessError expected) {
 349             check_expected(expected, msg);
 350         }
 351     }
 352 
 353     static void check_expected(Throwable expected, String msg) {
 354         if (!expected.getMessage().contains(msg))
 355             throw new Error("Wrong " + expected.getClass().getSimpleName() +": \"" +
 356                             expected.getMessage() + "\" does not contain \"" +
 357                             msg + "\"");
 358         System.out.println("OK - got expected exception: " + expected);
 359     }
 360 }