8246337: Add more JVM tests for sealed classes

Add missing test cases for sealed interfaces and sealed classes.

Reviewed-by: dholmes, lfoltan
This commit is contained in:
Harold Seigel 2020-06-26 12:38:00 +00:00
parent e7fa180e05
commit 51ddc2adbf
12 changed files with 378 additions and 20 deletions

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8225056 8246337
* @modules java.base/jdk.internal.misc
* @library /test/lib ..
* @compile sealedP1/SuperInterface.jcod
* @compile --enable-preview --source ${jdk.version} sealedP1/C1.java sealedP2/C2.java sealedP3/C3.java
* @build sun.hotspot.WhiteBox
* @compile/module=java.base java/lang/ModuleHelper.java
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. --enable-preview -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SealedInterfaceModuleTest
*/
public class SealedInterfaceModuleTest {
// Test sub-classing a sealed super interface in a named module. In this test,
// sealed interface sealedP1/SuperInterface permits sealedP1.C1, sealedP2.C2, and
// sealedP3.C3. All three of those classes implement sealedP1/SuperInterface.
public static void main(String args[]) throws Throwable {
Object m1x, m2x;
// Get the class loader for SealedInterfaceModuleTest and assume it's also used
// to load the other classes.
ClassLoader this_cldr = AccessCheckRead.class.getClassLoader();
// Define a module for packages sealedP1 and sealedP2.
m1x = ModuleHelper.ModuleObject("module_one", this_cldr,
new String[] { "sealedP1", "sealedP2" });
ModuleHelper.DefineModule(m1x, false, "9.0", "m1x/here",
new String[] { "sealedP1", "sealedP2" });
// Define a module for package sealedP3 with the same class loader.
m2x = ModuleHelper.ModuleObject("module_two", this_cldr, new String[] { "sealedP3" });
ModuleHelper.DefineModule(m2x, false, "9.0", "m2x/there", new String[] { "sealedP3" });
// Make package sealedP1 in m1x visible to everyone because it contains
// the sealed super interface for C1, C2, and C3.
ModuleHelper.AddModuleExportsToAll(m1x, "sealedP1");
ModuleHelper.AddReadsModule(m2x, m1x);
// Test subtype in the same named package and named module as its super
// interface. This should succeed.
// Class sealedP1.C1 implements interface sealedP1.SuperInterface.
Class p1_C1_class = Class.forName("sealedP1.C1");
// Test non-public class in same module but different package than its
// super interface. This should throw ICCE.
// Class sealedP2.C2 implements interface class sealedP1.SuperInterface.
try {
Class p2_C2_class = Class.forName("sealedP2.C2");
throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown");
} catch (IncompatibleClassChangeError e) {
if (!e.getMessage().contains("cannot implement sealed interface")) {
throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
}
}
// Test subtype in a different module than its super type. This should
// fail even though they have the same class loader.
// Class sealedP3.C3 implements interface sealedP1.SuperInterface.
try {
Class p3_C3_class = Class.forName("sealedP3.C3");
throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown");
} catch (IncompatibleClassChangeError e) {
if (!e.getMessage().contains("cannot implement sealed interface")) {
throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
}
}
}
}

View File

@ -24,7 +24,7 @@
// Small class used by SealedModuleTest
package sealedP1;
public final class C1 extends sealedP1.SuperClass {
public final class C1 extends sealedP1.SuperClass implements sealedP1.SuperInterface {
public C1() { }
}

View File

@ -103,3 +103,46 @@ class sealedP1/SuperClass {
} // end PermittedSubclasses
} // Attributes
} // end class sealedP1/SuperClass
// This is an empty interface that is needed because the subtypes used by test
// SealedModuleTest are also used by test SealedInterfaceModuleTest, which
// tests a sealed interface with this same name.
//
// package sealedP1;
// public interface SuperInterface { }
//
class sealedP1/SuperInterface {
0xCAFEBABE;
0; // minor version
60; // version
[7] { // Constant Pool
; // first element is empty
class #2; // #1 at 0x0A
Utf8 "sealedP1/SuperInterface"; // #2 at 0x0D
class #4; // #3 at 0x27
Utf8 "java/lang/Object"; // #4 at 0x2A
Utf8 "SourceFile"; // #5 at 0x3D
Utf8 "SuperInterface.java"; // #6 at 0x4A
} // Constant Pool
0x0601; // access [ ACC_PUBLIC ACC_INTERFACE ]
#1;// this_cpx
#3;// super_cpx
[0] { // Interfaces
} // Interfaces
[0] { // fields
} // fields
[0] { // methods
} // methods
[1] { // Attributes
Attr(#5, 2) { // SourceFile at 0x6E
#6;
} // end SourceFile
} // Attributes
} // end class sealedP1/SuperInterface

View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// This sealed class cannot be a java file because its permits clause names
// a class in another package causing javac to issue a compilation error.
//
// Sealed super interface used by SealedInterfaceModuleTest.
//
// package sealedP1;
//
// public sealed interface SuperInterface permits sealedP1.C1, sealedP2.C2, sealedP3.C3 { }
//
class sealedP1/SuperInterface {
0xCAFEBABE;
65535; // minor version
60; // version
[14] { // Constant Pool
; // first element is empty
class #2; // #1 at 0x0A
Utf8 "sealedP1/SuperInterface"; // #2 at 0x0D
class #4; // #3 at 0x27
Utf8 "java/lang/Object"; // #4 at 0x2A
Utf8 "SourceFile"; // #5 at 0x3D
Utf8 "SuperInterface.java"; // #6 at 0x4A
Utf8 "PermittedSubclasses"; // #7 at 0x60
class #9; // #8 at 0x76
Utf8 "sealedP1/C1"; // #9 at 0x79
class #11; // #10 at 0x87
Utf8 "sealedP2/C2"; // #11 at 0x8A
class #13; // #12 at 0x98
Utf8 "sealedP3/C3"; // #13 at 0x9B
} // Constant Pool
0x0601; // access [ ACC_PUBLIC ACC_INTERFACE ]
#1;// this_cpx
#3;// super_cpx
[0] { // Interfaces
} // Interfaces
[0] { // fields
} // fields
[0] { // methods
} // methods
[2] { // Attributes
Attr(#5, 2) { // SourceFile at 0xB7
#6;
} // end SourceFile
;
Attr(#7, 8) { // PermittedSubclasses at 0xBF
0x00030008000A000C;
} // end PermittedSubclasses
} // Attributes
} // end class sealedP1/SuperInterface
// This is an empty class that is needed because the subtypes used by test
// SealedInterfaceModuleTest are also used by test SealedoduleTest, which
// tests a sealed class with this same name.
//
// package sealedP1;
//
// public class SuperClass { }
//
class sealedP1/SuperClass {
0xCAFEBABE;
0; // minor version
60; // version
[13] { // Constant Pool
; // first element is empty
Method #2 #3; // #1 at 0x0A
class #4; // #2 at 0x0F
NameAndType #5 #6; // #3 at 0x12
Utf8 "java/lang/Object"; // #4 at 0x17
Utf8 "<init>"; // #5 at 0x2A
Utf8 "()V"; // #6 at 0x33
class #8; // #7 at 0x39
Utf8 "sealedP1/SuperClass"; // #8 at 0x3C
Utf8 "Code"; // #9 at 0x52
Utf8 "LineNumberTable"; // #10 at 0x59
Utf8 "SourceFile"; // #11 at 0x6B
Utf8 "SuperClass.java"; // #12 at 0x78
} // Constant Pool
0x0021; // access [ ACC_PUBLIC ACC_SUPER ]
#7;// this_cpx
#2;// super_cpx
[0] { // Interfaces
} // Interfaces
[0] { // fields
} // fields
[1] { // methods
{ // Member at 0x96
0x0001; // access
#5; // name_cpx
#6; // sig_cpx
[1] { // Attributes
Attr(#9, 29) { // Code at 0x9E
1; // max_stack
1; // max_locals
Bytes[5]{
0x2AB70001B1;
}
[0] { // Traps
} // end Traps
[1] { // Attributes
Attr(#10, 6) { // LineNumberTable at 0xB5
[1] { // LineNumberTable
0 3; // at 0xC1
}
} // end LineNumberTable
} // Attributes
} // end Code
} // Attributes
} // Member
} // methods
[1] { // Attributes
Attr(#11, 2) { // SourceFile at 0xC3
#12;
} // end SourceFile
} // Attributes
} // end class sealedP1/SuperClass

View File

@ -24,6 +24,6 @@
// Small class used by SealedModuleTest
package sealedP2;
final class C2 extends sealedP1.SuperClass {
final class C2 extends sealedP1.SuperClass implements sealedP1.SuperInterface {
public void method2() { }
}

View File

@ -24,6 +24,6 @@
// Small class used by SealedModuleTest
package sealedP3;
public final class C3 extends sealedP1.SuperClass {
public final class C3 extends sealedP1.SuperClass implements sealedP1.SuperInterface {
public void method3() { }
}

View File

@ -26,13 +26,13 @@
//
// package Pkg;
//
// sealed public interface SealedInterface permits Permitted, otherPkg.WrongPackage { }
// sealed public interface SealedInterface permits Permitted, otherPkg.WrongPackage, otherPkg.WrongPackageNotPublic { }
class Pkg/SealedInterface {
0xCAFEBABE;
65535; // minor version
60; // version
[12] { // Constant Pool
[14] { // Constant Pool
; // first element is empty
class #2; // #1 at 0x0A
Utf8 "Pkg/SealedInterface"; // #2 at 0x0D
@ -45,6 +45,8 @@ class Pkg/SealedInterface {
Utf8 "Pkg/Permitted"; // #9 at 0x74
class #11; // #10 at 0x84
Utf8 "otherPkg/WrongPackage"; // #11 at 0x87
class #13; // #12
Utf8 "otherPkg/WrongPackageNotPublic"; // #13
} // Constant Pool
0x0601; // access [ ACC_PUBLIC ACC_INTERFACE ]
@ -65,8 +67,8 @@ class Pkg/SealedInterface {
#6;
} // end SourceFile
;
Attr(#7, 6) { // PermittedSubtclasses at 0xB5
0x00020008000A;
Attr(#7, 8) { // PermittedSubtclasses at 0xB5
0x00030008000A000C;
} // end PermittedSubclasses
} // Attributes
} // end class Pkg/SealedInterface

View File

@ -25,7 +25,7 @@
* @test
* @bug 8225056
* @compile Pkg/SealedInterface.jcod Pkg/NotPermitted.jcod
* @compile --enable-preview -source ${jdk.version} Pkg/Permitted.java otherPkg/WrongPackage.java
* @compile --enable-preview -source ${jdk.version} Pkg/Permitted.java otherPkg/WrongPackage.java otherPkg/WrongPackageNotPublic.java
* @run main/othervm --enable-preview SealedUnnamedModuleIntfTest
*/
@ -33,14 +33,18 @@ public class SealedUnnamedModuleIntfTest {
public static void main(String args[]) throws Throwable {
// Classes Permitted, NotPermitted, and WrongPackage all try to implement
// Classes Permitted, NotPermitted, WrongPackage and WrongPackageNotPublic all try to implement
// sealed interface SealedInterface.
// Interface SealedInterface permits classes Permitted and WrongPackage.
// Interface SealedInterface permits classes Permitted, WrongPackage, and WrongPackageNotPublic;
// Test non-public permitted subclass and superclass in unnamed module and
// same package. This should succeed.
Class permitted = Class.forName("Pkg.Permitted");
// Test public permitted subclass and superclass in same unnamed module but in
// different packages. This should not throw an exception.
Class wrongPkg = Class.forName("otherPkg.WrongPackage");
// Test unpermitted subclass and superclass in unnamed module and same package.
// This should throw an exception.
try {
@ -52,8 +56,15 @@ public class SealedUnnamedModuleIntfTest {
}
}
// Test public permitted subclass and superclass in same unnamed module but in
// different packages. This should not throw an exception.
Class wrongPkg = Class.forName("otherPkg.WrongPackage");
// Test non-public permitted subclass and superclass in same unnamed module but
// in different packages. This should throw an exception.
try {
Class notPermitted = Class.forName("otherPkg.WrongPackageNotPublic");
throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown");
} catch (IncompatibleClassChangeError e) {
if (!e.getMessage().contains("cannot implement sealed interface")) {
throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
}
}
}
}

View File

@ -25,7 +25,7 @@
* @test
* @bug 8225056
* @compile planets/OuterPlanets.jcod planets/Mars.jcod
* @compile --enable-preview -source ${jdk.version} planets/Neptune.java asteroids/Pluto.java
* @compile --enable-preview -source ${jdk.version} planets/Neptune.java asteroids/Pluto.java asteroids/Charon.java
* @run main/othervm --enable-preview SealedUnnamedModuleTest
*/
@ -33,8 +33,8 @@ public class SealedUnnamedModuleTest {
public static void main(String args[]) throws Throwable {
// Classes Neptune, Mars, and Pluto all try to extend sealed class OuterPlanets.
// Class OuterPlanets permits Nepturn and Pluto.
// Classes Neptune, Mars, Pluto, and Charon all try to extend sealed class OuterPlanets.
// Class OuterPlanets permits Nepturn, Pluto, and Charon.
// Test permitted subclass and superclass in unnamed module and same package.
// This should succeed.
@ -61,5 +61,9 @@ public class SealedUnnamedModuleTest {
throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage());
}
}
// Test public permitted subclass and superclass in same unnamed module but
// in different packages. This should succeed.
Class charon = Class.forName("asteroids.Charon");
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package asteroids;
public final class Charon extends planets.OuterPlanets { }

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package otherPkg;
final class WrongPackageNotPublic implements Pkg.SealedInterface { }

View File

@ -23,13 +23,13 @@
// package planets;
//
// sealed public class OuterPlanets permits Neptune, asteroids.Pluto { }
// sealed public class OuterPlanets permits Neptune, asteroids.Pluto, asteroids.Charon { }
class planets/OuterPlanets {
0xCAFEBABE;
65535; // minor version
60; // version
[18] { // Constant Pool
[20] { // Constant Pool
; // first element is empty
Method #2 #3; // #1 at 0x0A
class #4; // #2 at 0x0F
@ -48,6 +48,8 @@ class planets/OuterPlanets {
Utf8 "planets/Neptune"; // #15 at 0xA4
class #17; // #16 at 0xB6
Utf8 "asteroids/Pluto"; // #17 at 0xB9
class #19; // #18 at 0xB6
Utf8 "asteroids/Charon"; // #19
} // Constant Pool
0x0021; // access [ ACC_PUBLIC ACC_SUPER ]
@ -91,8 +93,8 @@ class planets/OuterPlanets {
#12;
} // end SourceFile
;
Attr(#13, 6) { // PermittedSubclasses at 0x010C
0x0002000E0010;
Attr(#13, 8) { // PermittedSubclasses at 0x010C
0x0003000E00100012;
} // end PermittedSubclasses
} // Attributes
} // end class planets/OuterPlanets