1 /*
   2  * Copyright (c) 2013, 2018, 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 package vm.runtime.defmeth;
  25 
  26 import nsk.share.TestFailure;
  27 import nsk.share.test.TestBase;
  28 import vm.runtime.defmeth.shared.MemoryClassLoader;
  29 import vm.runtime.defmeth.shared.annotation.KnownFailure;
  30 import vm.runtime.defmeth.shared.annotation.NotApplicableFor;
  31 import vm.runtime.defmeth.shared.builder.TestBuilder;
  32 import vm.runtime.defmeth.shared.data.*;
  33 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  34 import vm.runtime.defmeth.shared.DefMethTest;
  35 
  36 import java.util.Map;
  37 
  38 import static vm.runtime.defmeth.shared.ExecutionMode.*;
  39 
  40 /**
  41  * Basic tests on some of the assertions from JVMS.
  42  */
  43 public class BasicTest extends DefMethTest {
  44 
  45     public static void main(String[] args) {
  46         TestBase.runTest(new BasicTest(), args);
  47     }
  48 
  49     /*
  50      * JVMS 6.5 invokevirtual
  51      *
  52      * ...
  53      *
  54      * Runtime Exceptions
  55      *
  56      * Otherwise, if the resolved method is not signature polymorphic:
  57      *
  58      */
  59 
  60     /*
  61      * ...
  62      *
  63      * If the resolved method is declared in an interface and the class of
  64      * objectref does not implement the resolved interface, invokevirtual throws
  65      * an IncompatibleClassChangeError.
  66      */
  67     @KnownFailure(modes = {
  68         REFLECTION,                           // throws IAE
  69         INVOKE_GENERIC, INVOKE_WITH_ARGS})    // throws ClassCastException
  70     public void testInterfaceNotImplemented() {
  71         TestBuilder b = factory.getBuilder();
  72 
  73         Interface I = b.intf("I")
  74                 .defaultMethod("m", "()V").emptyBody().build()
  75             .build();
  76 
  77         ConcreteClass C = b.clazz("C").build();
  78 
  79         Class expectedClass;
  80         if (factory.getExecutionMode().equals("REFLECTION")) {
  81             expectedClass = IllegalArgumentException.class;
  82         } else if (factory.getExecutionMode().equals("INVOKE_WITH_ARGS")) {
  83             // Notes from JDK-8029926 which details reasons behind CCE.
  84         // The code below demonstrates the use of a MethodHandle
  85             // of kind REF_invokeInterface pointing to method I.m.
  86             // Because 'invoke' is called, this MethodHandle is effectively
  87             // wrapped in the type adaptations necessary to accept a C
  88             // as the first argument. ***Before we even get to the point
  89             // of the invokeinterface call to I.m***, the adaptation
  90             // code must run, and that is where the ClassCastException occurs.
  91             // This exception can be thrown from code that is cleanly
  92             // compiled and does no bytecode generation, so an ICCE would
  93         // be inappropriate since no classes are changed.
  94             expectedClass = ClassCastException.class;
  95         } else {
  96             expectedClass = IncompatibleClassChangeError.class;
  97         }
  98 
  99         b.test().callSite(I, C, "m", "()V").throws_(expectedClass).done()
 100 
 101         .run();
 102     }
 103 
 104     /*
 105      * ...
 106      *
 107      * Otherwise, if no method matching the resolved name and descriptor is
 108      * selected, invokevirtual throws an NoSuchMethodError.
 109      *
 110      * ...
 111      */
 112     @KnownFailure(modes = {
 113         DIRECT, REFLECTION, INVOKE_WITH_ARGS, // NSME, instead of AME
 114         INVOKE_EXACT, INVOKE_GENERIC, INDY})        // IncompatibleClassChangeError, instead of AME
 115     public void testNoMatch() {
 116         TestBuilder b = factory.getBuilder();
 117 
 118         Interface I = b.intf("I")
 119                 .defaultMethod("m", "(Ljava/lang/Object;)V").emptyBody().build()
 120             .build();
 121 
 122         ConcreteClass C = b.clazz("C").implement(I).build();
 123 
 124         b.test().callSite(C, C, "m",  "()I").throws_(NoSuchMethodError.class).done()
 125          .test().callSite(C, C, "m1", "()V").throws_(NoSuchMethodError.class).done()
 126          .test().callSite(C, C, "m", "(I)V").throws_(NoSuchMethodError.class).done()
 127 
 128         .run();
 129     }
 130 
 131     /*
 132      * ...
 133      *
 134      * 8025604: Updated specification text for both 5.4.3.3 and 5.4.4.4
 135      * "Otherwise, if any superinterface of C declares a method with the name and
 136      * descriptor specified by the method reference that has set neither
 137      * its ACC_PRIVATE flag nor its ACC_STATIC flag, one of these is arbitrarily
 138      * chosen and method lookup succeeds."
 139      * If method lookup fails, method resolution throws a NoSuchMethodError
 140      *
 141      * ...
 142      */
 143     public void testNonPublic() {
 144         TestBuilder b = factory.getBuilder();
 145 
 146         Interface I = b.intf("I")
 147                 .defaultMethod("m1", "()V").private_().emptyBody().build()
 148                 .defaultMethod("m2", "()I").private_().returns(1).build()
 149             .build();
 150 
 151         ConcreteClass C = b.clazz("C").implement(I).build();
 152 
 153         b.test().callSite(C, C, "m1",  "()V").throws_(NoSuchMethodError.class).done()
 154          .test().callSite(C, C, "m2",  "()I").throws_(NoSuchMethodError.class).done()
 155 
 156         .run();
 157     }
 158 
 159     /*
 160      * Default method override w/ non-public concrete method
 161      *
 162      * interface I { void m() default {} }
 163      * class C implements I {
 164      *   [private/package-private/protected]
 165      *   void m() {}
 166      * }
 167      *
 168      */
 169     @KnownFailure(modes = {INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY}) // NPE, instead of IAE
 170     public void testNonPublicOverride() {
 171         TestBuilder b = factory.getBuilder();
 172 
 173         Interface I = b.intf("I")
 174                 .defaultMethod("m","()V").emptyBody().build()
 175             .build();
 176 
 177         ConcreteClass C = b.clazz("C").implement(I)
 178                 .concreteMethod("m", "()V").private_().emptyBody().build()
 179             .build();
 180 
 181         ConcreteClass D = b.clazz("D").implement(I)
 182                 .concreteMethod("m", "()V").protected_().emptyBody().build()
 183             .build();
 184 
 185          ConcreteClass E = b.clazz("E").implement(I)
 186                 .concreteMethod("m", "()V").package_private().emptyBody().build()
 187             .build();
 188 
 189         b.test().callSite(I, C, "m", "()V").throws_(IllegalAccessError.class).done()
 190          .test().callSite(I, D, "m", "()V").throws_(IllegalAccessError.class).done()
 191          .test().callSite(I, E, "m", "()V").throws_(IllegalAccessError.class).done()
 192 
 193         .run();
 194     }
 195 
 196 
 197     /**
 198      * interface I {
 199      *   static { throw new RE()}
 200      *   public default void m() {}
 201      * }
 202      *
 203      * class C implements I {}
 204      *
 205      * TEST: C c = new C(); ==> LinkageError
 206      * Static initialization of class C will trigger
 207      * I's static initialization due to I's default method.
 208      */
 209     public void testStaticInit() throws ClassNotFoundException {
 210         TestBuilder b = factory.getBuilder();
 211 
 212         Interface I = b.intf("I")
 213                 .defaultMethod("<clinit>", "()V")
 214                     .flags(ACC_STATIC)
 215                     .throw_(RuntimeException.class)
 216                     .build()
 217 
 218                 .defaultMethod("m", "()V")
 219                     .emptyBody().build()
 220                 .build();
 221 
 222         ConcreteClass C = b.clazz("C").implement(I).build();
 223 
 224         b.test().callSite(I, C, "m", "()V").throws_(LinkageError.class).done()
 225 
 226         .run();
 227     }
 228 
 229     /**
 230      * interface I {
 231      *   static { throw new RE()}
 232      *   private default void m() {}
 233      * }
 234      *
 235      * class C implements I {}
 236      *
 237      * TEST: C c = new C(); ==> LinkageError
 238      * Static initialization of class C will trigger
 239      * I's static initialization due to I's private concrete method.
 240      */
 241     public void testStaticInitPrivate() throws ClassNotFoundException {
 242         TestBuilder b = factory.getBuilder();
 243 
 244         Interface I = b.intf("I")
 245                 .defaultMethod("<clinit>", "()V")
 246                     .flags(ACC_STATIC)
 247                     .throw_(RuntimeException.class)
 248                     .build()
 249 
 250                 .defaultMethod("m", "()V")
 251                     .flags(ACC_PRIVATE)
 252                     .emptyBody().build()
 253                 .build();
 254 
 255         ConcreteClass C = b.clazz("C").implement(I).build();
 256 
 257         Class expectedClass;
 258         if (factory.getExecutionMode().equals("REFLECTION")) {
 259             expectedClass = NoSuchMethodException.class;
 260         } else {
 261             expectedClass = LinkageError.class;
 262         }
 263         b.test().callSite(I, C, "m", "()V").throws_(expectedClass).done()
 264 
 265         .run();
 266     }
 267 
 268     /**
 269      * interface I {
 270      *   static { throw new RE()}
 271      * }
 272      * interface J {
 273      *   public default int m() { return 1}
 274      *
 275      * class C implements I,J {}
 276      *
 277      * TEST: C c = new C()
 278      *       c.m() returns 1
 279      * Static initialization of class C will not trigger
 280      * I's static initialization since I has no concrete methods.
 281      */
 282     public void testNotStaticInitNoDefault() throws ClassNotFoundException {
 283         TestBuilder b = factory.getBuilder();
 284 
 285         Interface I = b.intf("I")
 286                 .defaultMethod("<clinit>", "()V")
 287                     .flags(ACC_STATIC)
 288                     .throw_(RuntimeException.class)
 289                     .build()
 290                  .build();
 291 
 292         Interface J = b.intf("J")
 293                 .defaultMethod("m", "()I")
 294                     .returns(1).build()
 295                 .build();
 296 
 297         ConcreteClass C = b.clazz("C").implement(I,J).build();
 298 
 299         b.test().callSite(C, C, "m", "()I").returns(1).done()
 300 
 301         .run();
 302     }
 303 
 304     /*
 305      * Example A.10
 306      *
 307      * Let L1 and L2 be class loaders with different interpretations of the type "A".
 308      *
 309      * Loaded by L1:
 310      * public interface I { public default A m() { return null; } }
 311      *
 312      * Loaded by L2:
 313      * public class C implements I {}
 314      *
 315      * TEST: I o = new C(); o.m() ==> LinkageError;
 316      * TEST: C o = new C(); o.m() ==> LinkageError;
 317      */
 318     // disabling this test for REFLECTION and INVOKE for now until
 319     // loader constraint issue associated with those modes has been resolved
 320     @NotApplicableFor(modes = { REFLECTION, INVOKE_WITH_ARGS, INVOKE_EXACT, INVOKE_GENERIC, INDY })
 321     public void testLoaderConstraint() throws Exception{
 322         TestBuilder b = factory.getBuilder();
 323 
 324         ConcreteClass A = b.clazz("A").build();
 325 
 326         Interface I = b.intf("I")
 327                 .defaultMethod("m", "()LA;").returnsNewInstance(A).build()
 328                 .build();
 329 
 330         ConcreteClass C = b.clazz("C").implement(I).build();
 331 
 332         b.test().callSite(I, C, "m", "()LA;").throws_(LinkageError.class).done()
 333          .test().callSite(C, C, "m", "()LA;").throws_(LinkageError.class).done()
 334 
 335          .prepare(new TestBuilder.LoaderConstructor() {
 336                 @Override
 337                 public MemoryClassLoader construct(Map<String, byte[]> classFiles) {
 338                     final byte[] cfI = classFiles.get("I");
 339                     final byte[] cfC = classFiles.get("C");
 340                     final byte[] cfA = classFiles.get("A");
 341                     final byte[] cfT1 = classFiles.get("Test1_I_C_m");
 342                     final byte[] cfT2 = classFiles.get("Test2_C_C_m");
 343 
 344                     final ClassLoader l1 = new ClassLoader() {
 345                         @Override
 346                         protected Class<?> findClass(String name) throws ClassNotFoundException {
 347                             switch (name) {
 348                                 case "I":
 349                                     return defineClass(name, cfI, 0, cfI.length);
 350                                 case "A":
 351                                     return defineClass(name, cfA, 0, cfA.length);
 352                                 default:
 353                                     throw new ClassNotFoundException(name);
 354                             }
 355                         }
 356                     };
 357 
 358                     final MemoryClassLoader l2 = new MemoryClassLoader(classFiles) {
 359                         @Override
 360                         public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
 361                             if ("I".equals(name)) {
 362                                 return l1.loadClass(name);
 363                             } else {
 364                                 return super.loadClass(name, resolve);
 365                             }
 366                         }
 367                     };
 368 
 369                     try {
 370                         // Need to preload classes, otherwise A will be resolved in the same loader
 371                         l1.loadClass("A"); l1.loadClass("I");
 372                         l2.loadClass("A"); l2.loadClass("C");
 373                     } catch (ClassNotFoundException e) {
 374                         throw new TestFailure(e);
 375                     }
 376 
 377                     return l2;
 378                 }
 379             }).run();
 380     }
 381 }